""" Code Python 3.9, encodé en UTF-8 Ce programme liste le nom des dossiers et des fichiers qui ne respecte pas la règle 66 et ayant plus de 32 caractères. Pour ne pas nuire à la rapidité, le programme ne mentionne pas les fichiers commençant par . ou par ~, ayant un chiffre dans les 3 premiers caractères, contenant --, ... version 4 - 2022-11-20 00:09 - À Â Ç É È Ê Ë Î Ï Ô Ù Û Ü Ÿ Æ Œ æ œ """ # Les importations ============================================================= import re; import os; import platform from datetime import datetime; import datetime # import après from ! import tkinter as tk; from tkinter import * from tkinter import messagebox; from tkinter import filedialog # Affectations des constantes pour les noms ==================================== DIGIT = "0123456789" # = 10 caractères ALPHA = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" # = 52 caractères FILENAME = ALPHA+DIGIT+"-_" # nom de fichier sans extension # = 64 caractères CARAC_66 = FILENAME+".~"# les 66 caractères simples dans une URL (fichier) NB_CARAC_MAX = 32 NL = "\n"; DIR_DEV="/zZ" # ne pas modifier ce nom cfr "analysDir.py" # Les déclarations des variables globales pour les fichiers ==================== gPath = os.path.abspath("."); SEP="/" if platform.system() == "Windows": SEP="\\"#; gPath=os.path.abspath("C:\\Users"); # Création de l'interface root = Tk () root.withdraw() def regEx(mot, caracOK = CARAC_66, longMin = 1, longMax = NB_CARAC_MAX, isVerbeux = False): #-------------------------------------------------- """ La fonction retourne True ou False selon que le mot correspond au pattern ou pas. ..warning:: Le mot doit être débarassé des espaces du début et de fin avant d'être envoyé à cette fonction, car elle ne modifie pas le mot passé à la fonction. " 123 " (au lieu de "123") pourrait être enregistré dans la DB :param str mot: La string à tester. :param str caracOK: DIGIT | ALPHA | FILENAME | CARAC_66 :param str longMin: Nombre minimal de caractères :param int longMax: Nombre maximal de caractères :param bool isVerbeux: si True affiche des messages (si problème) Elle requiert : import re :return: Retourne True si le mot ne contient pas de caractères interdits :rtype: bool 2022-10-15 14:47:00 """ if mot is None: return False if len(mot)<longMin: if isVerbeux: messagebox.showwarning("Trop court","Pas assez de caractères.") return False if len(mot)>longMax: if isVerbeux: messagebox.showwarning("Trop long","Trop de caractères.") return False mot2 = mot.replace("-","") try: if(re.search("[^"+caracOK+"]", mot2)): return False except: messagebox.showwarning("Recommencer","Certains caractères posent problème.") return False return True def listDirs(rootdir, exclu = "", withParent = True): #------------------------- """ Fonction (non récursive) qui utilise une boucle WHILE pour lister les dossiers-enfants (et petit-enfants) :param str rootdir: Chemin complet du dossier (parent) Exemple (sous Windows) = X:/dossiers/sous-dossiers (sans slash final) NB : La valeur de "rootdir" provient de "filedialog.askdirectory()" => pas de "backslash" => pas X:\dossiers\sous-dossiers :param str exclu: String dans le chemin qui l'exclut Exemple : si exclu="zZ", les chemins suivants sont exclus : X:\dossiers\zZ\old X:\dossiers\sous-dossiers\zZ ... :param bool withParent : Si False, retourne que les descendants Requiert l'importation de : os :return: Un tableau contenant la liste des chemins du dossier parent et de ses dossiers descendants, utilisant le séparateur de l'OS, sans ce séparateur final Exemple (sous Windows) : X:\dossiers\sous-dossiers\enfant1 X:\dossiers\sous-dossiers\enfant1\petit-enfant ... :rtype: list 2022-11-19 19:27:04 """ dossiers = [] # liste des chemins du dossier-parent et de ses descendants # (avec le caractère de séparation des noms dépendant de l'OS) dossiers.append(rootdir) # ajoute le dossier parent i=0 # index en cours print("Recherche en cours ... dans :", rootdir, " exclure :", exclu, " avec parent :", str(withParent)) if len(exclu)>0: while i < len(dossiers): x = dossiers[i]#; print(str(i), str(len(dossiers))) for file in os.listdir(x): d = os.path.join(x, file) if os.path.isdir(d): if exclu not in d : dossiers.append(d) i +=1 else: while i < len(dossiers): x = dossiers[i]#; print(str(i), str(len(dossiers))) for file in os.listdir(x): d = os.path.join(x, file) if os.path.isdir(d): dossiers.append(d) i +=1 if not withParent: dossiers.pop(0) return dossiers # ============================================================================== dossier = gPath while True: gVerbeux = False lstDossiers = [] lstDossiersKO = [] gListFichiersKO = [] # Sélection du dossier folder = filedialog.askdirectory(initialdir = dossier, title = "Sélection d'un dossier") dossier = folder.replace("/",SEP) #; print(dossier) # chemin complet du dossier choisi if len(dossier)==0 : exit() if not os.path.exists(dossier+DIR_DEV): os.makedirs(dossier+DIR_DEV) #print("---", dossier) dossier = dossier.replace("/",SEP); isAll = False if messagebox.askyesno("Sous-dossiers", "Faut-il étendre l'analyse aux sous-dossiers ?"): lstDossiers = listDirs(dossier); isAll = True else: lstDossiers.append(dossier) # À ce stade, la liste des dossiers à analyser (lstDossiers) est établie nbDossiers = len(lstDossiers) if nbDossiers > 10 : if not messagebox.askyesno(str(nbDossiers)+ " sous-dossiers !", "Faut-il continuer ?"): print("Bye !"); exit() # Début de la création du rapport ---------------------------------------------- # Création de la date-time du rapport rapport = datetime.datetime.today().strftime('%Y-%m-%d %H:%M:%S') rapport += " --- analysé par 'listNot66.py'"+NL if nbDossiers > 1 : rapport +="Dossier parent : "+dossier+NL+NL else: rapport +="Dossier : "+dossier+NL+NL nbFichiers = 0 for d in lstDossiers: with os.scandir(d) as it: for entry in it: if entry.is_dir(): if not regEx(entry.name): lstDossiersKO.append(d) # test sur le dernier sous-dossier if entry.is_file(): nbFichiers +=1 if not regEx(entry.name): gListFichiersKO.append(d+SEP+entry.name) # Création du fichier-rapport dans le dossier analysé nbDossiersKO = len(lstDossiersKO) nbFichiersKO = len(gListFichiersKO) rapport += "Nombre de noms de dossiers non conformes : "+str(nbDossiersKO)+" sur " +str(len(lstDossiers))+NL rapport += "Nombre de noms de fichiers non conformes : "+str(nbFichiersKO)+" sur " +str(nbFichiers)+NL+NL if nbDossiersKO >0 or nbFichiersKO >0: if messagebox.askyesno(str(nbDossiersKO+nbFichiersKO)+" noms non valides", "Faut-il lister tous les noms ?"): gVerbeux = True if gVerbeux: if len(lstDossiersKO)>0: rapport += "Liste des dossiers ayant un nom"+NL rapport += "de plus de "+str(NB_CARAC_MAX)+" caractères et/ou non conforme à la 'règle 66' :"+NL+NL bloc = "" for d in lstDossiersKO: bloc += d+NL if len(bloc)>0: rapport += bloc+NL+NL if len(gListFichiersKO)>0: rapport += "Liste des fichiers ayant un nom"+NL rapport += "de plus de "+str(NB_CARAC_MAX)+" caractères et/ou non conforme à la 'règle 66' :"+NL+NL bloc = "" for d in gListFichiersKO: bloc += d+NL if len(bloc)>0: rapport += bloc print(rapport) if messagebox.askyesno(dossier, "Faut-il y créer le fichier-rapport ?"): cc = dossier+DIR_DEV+"/listNot66.txt" try: f = open(cc, "w", encoding='utf-8'); f.write(rapport); print(cc+" créé."+NL+"."*80+NL+NL) except: print("Impossible d'écrire "+cc) messagebox.showerror("Impossible d'enregistrer le rapport",cc) finally: try: f.close() # Fermer un fichier dans tous les cas (= bonne pratique) except: print("Le fichier n'a pas été fermé") if not messagebox.askyesno("Encore ?","Faut-il analyser un autre dossier ?"): break root.destroy() root.mainloop()