#! /usr/bin/python3 # Recherche de fichiers par expression régulière dans une arborescence # Jean-Christophe Beumier - 2023.05.09 - 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 ="!" # marque d'un répertoire non ouvert normal ="" # ne fait rien 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", "var", "root", "proc") # 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 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 . désigne n'importe quel caractère sauf un retour-chariot \w désigne une lettre ou un chiffre (équivaut à [A-Za-z0-9]) \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 ? suit un caractère ou (groupe) optionnel: roc(he)? = roc ou roche + 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)