#! /usr/bin/python3 # Recherche de fichiers par expression régulière dans une arborescence # Jean-Christophe Beumier - 2024.12.08 - autodocumenté ! # GPL 3.0 : https://www.gnu.org/licenses/gpl-3.0.en.html # écrit pour UNIX! À adapter pour Windows ou MacIntosh # module "os" pour lancer un fichier par une application # module "re" pour les expressions régulières # module "sys" pour le système d'exploitation import os, re, sys sep =os.sep # séparateur de répertoires: '/', '\' ou ':' # codes ECMA-48 pour console LINUX habituelle (blanc sur fond noir) if "linux" in sys.platform : jaune ="\033[33;1m" # couleur du texte du répertoire non ouvert rouge ="\033[31;1m" # couleur du texte de la taille des fichiers normal ="\033[0m" # retour à la normale else: # pas standard sous Windows: à remplacer par "" ou autre chose jaune ="#" # marque du numéro de fichier rouge ="!" # préfixe un répertoire non ouvert normal ="" # ne marque fait mais se rencontre dans le script # Unix: /home/toto pour l'utilisateur 'toto' # Windows: qqch comme C:\MyFiles\ # Mac: ? ad0 ="/home/jc" # adresse racine initiale # répertoires à exclure, exemples pour un système UNIX exclus =(".wine") # routine récursive d'exploration de répertoire def explore(ad): # réception de l'adresse d'un répertoire global cpt # variable qui doit être accessible partout if ad.split(sep)[-1] in exclus : # si répertoire dans la liste des exclus print(f"\n{rouge} {ad} exclu!\n{normal}") return repertoire =os.listdir(ad) for element in repertoire: # exploration d'un sous-répertoire adresse =ad +sep +element if os.path.isdir(adresse): # récursivité si répertoire try: # on essaie explore(adresse) except: # si ça rate, on le dit print(f"{rouge} Non ouvert: {adresse} {normal}") else: if motif.search(element): # voir ligne 143 cpt +=1 ; scpt =str(cpt) taille ="%10d" %(os.path.getsize(adresse)) # taille sur 10 caractères # colore le numéro d'ordre en jaune ou le précède d'un # print(f"{taille} {jaune} {scpt} {normal} {adresse}") elements[scpt] =adresse # inscription dans le dictionnaire # applications à lancer selon l'extension : très certainement à modifier selon votre plateforme tt ="lowriter" # traitement de texte (libreoffice) calc ="localc" # feuille de calcul (libreoffice) pres ="loimpress" # fichiers de présentation (libreoffice) film ="vlc" htm ="firefox" # à modifier si vous n'utilisez pas Mate-Desktop : pdf ="atril" # visualisateur de pdf hx ="ghex" # vision hexadécimale (vaut pour Gnome) img ="eom" # visualisateur d'images txt ="pluma" # éditeur de textes simples gauche =" \"" # servent à entourer le nom du fichier... droite ="\" " # ...qui contient peut-être des espaces def afficher(q) : commandes =q.split() if q =="*" : # si l'étoile est choisie os.mkdir(chaine) # crée un répertoire du nom de la recherche for i in elements : os.system(f"cp '{elements[i]}' {chaine}") print(f"{elements[i]} copié") for q in commandes : # UNIX: & permet les lancements parallèles, pas recommandés (sons) # ou pas supportés par toutes les applications flg =0 if q[0] =="x" : q =q[1:] ; flg =1 if q in elements : fichier =elements[q] ext =fichier.rsplit(".")[-1].lower() # isole l'extension if flg : if ext in ("htm", "html") : os.system(f"{txt} '{fichier}' &") else : os.system(f"{hx} '{elements[qq]}' &") continue if ext =="pdf" : os.system(f"{pdf} '{fichier}' &") ; continue if ext in ("odt", "sxw", "doc", "rtf", "docx") : os.system(f"{tt} '{fichier}' &") ; continue if ext in ("ods", "xls") : os.system(f"{calc} '{fichier}' &") ; continue if ext in ("odp", "pps") : os.system(f"{pres} '{fichier}' &") ; continue if ext in ("gif", "jpg", "png", "bmp") : os.system(f"{img} '{fichier}' &") ; continue if ext in ("mp3", "wav", "ogg", "oga") : os.system(f"{film} '{fichier}' ") ; continue if ext in ("txt", "log", "php") : os.system(f"{txt} '{fichier}' &") ; continue if ext in ("htm", "html") : os.system(f"{htm} '{fichier}' &") ; continue if ext ==".py" : os.system("python3 '{fichier}' ") q ="" while q !="q" : # initialisation du dictionnaire des fichiers trouvés # clé: numéro d'ordre (format chaîne) # contenu: adresse complète du fichier retenu elements ={} cpt =0 print(""" === Recherche de fichier selon une expression régulière ===\n (voir jchr.be/python/modules.htm) . désigne n'importe quel caractère sauf un retour-chariot \w désigne un chiffre ou une lettre (latine ou non, diacritiques acceptés) \W désigne un caractère qui ne soit ni lettre ni chiffre \s désigne un caractère 'espace' (tab, retour, nouvelle ligne) \S désigne un caractère non espace tels que défini ci-dessus \d désigne un chiffre; équivaut à [0-9] \D désigne un caractère sauf les chiffres [A-Z^M] choisit un caractère (majuscule) de A à Z, sauf M [a-flk^d] choisit un caractère parmi a, b, c, e, f, l ou k () permet de traiter un groupe de caractères ou un choix : | permet un choix entre chaînes: (a|p)m représente am ou pm () permet également de préserver des chaînes dans le motif de remplacement, elle sont appelées avec \1 \2... | permet un choix entre chaînes: (a|p)m représente am ou pm ? suit un caractère ou (groupe) optionnel: roc(he)? = roc ou roche ? permet également un mode non gourmand pour les quatre suivants + suit un caractère ou (groupe) présent au moins une fois * suit un caractère ou (groupe) répété un nombre indéfini de fois {n} suit un caractère ou (groupe) répété exactement n fois {n,m} suit un caractère ou (groupe) répété de n à m fois ^ désigne le début: ^pot pour les fichiers commençant par pot $ désigne la fin: able$ pour les fichiers terminant par able \ préserve un caractère servant normalement au codage: \()[]{}.$^|?+* Ex: ^[Ss]t.+html?$ donne les fichiers .htm(l) commençant par St ou st """) chaine =input(" Fichiers à chercher selon l'expression régulière: ") motif =re.compile(chaine) # fabrique le motif de l'expression à rechercher # En UNIX, le répertoire par défaut de toto est /home/toto, équivalent à ~/ # utiliser ../ pour remonter d'un etage, ../../ pour remonter à la racine / repertoire =input(" Répertoire relatif à ~/") if repertoire: ad =ad0 +sep +repertoire else: ad =ad0 ad =os.path.realpath(ad) print() explore(ad) # lance la recherche dans le répertoire # rouge et normal: voir lignes 15-17 if cpt ==0: print(f" {rouge}Pas de fichier trouvé{normal}") q =input(""" [Enter] pour recommencer la recherche, 'q' + [enter] pour quitter saisir un nombre ouvre le fichier; accepte plusieurs nombres séparés d'espaces précéder le nombre d'un x pour une ouverture hexadécimale, ou un HTM(L) en fichier texte --- tous les fichiers ne sont pas nécessairement lancés en même temps --- * sauvegarde tous les fichiers dans un répertoire du nom de la recherche """) if q =="" : continue else : afficher(q)