# -*- coding: utf-8 -*- import os,os.path,string,re,shutil import time """ID/ACF : Historique des appels (par décoration ?) Historique des messages (et choix de sortie) Question Sous-répertoires (callback + récursivité ?) """ GlobalPVersion='1.14' class orep(object): """ La Classe 'orep' permet de définir un "répertoire de base", sur lequel on va pouvoir effectuer diverses manipulation. Les possibilités sont : - des filtres, pour sélectionner certains fichiers seulement ; à noter que les filtres sont cumulatifs (chaque filtre appliqué s'applique au résultat des filtres précédents) : - filtre I{annule le filtre ; réinitialise} - filtreext I{extensions} - filtredebut I{début du nom} - filtredatebasse I{fichiers postérieurs} - filtredatehaute I{fichiers antérieurs} - filtrere I{expression régulière} - filtretaille I{taille mini, maxi} - filtrenb I{nombre ; du, au} - filtreanti I{inversion de filtre} - cmpnom I{comparaison autre répertoire / noms} - cmpdt I{comparaison autre répertoire / différences} - cmpdiff I{comparaison autre répertoire / différences} - des tris du résultat des filtres : - trinom I{par noms} - tridate I{par dates/heures} - tritaille I{par taille} - des actions, sur le résultat des filtres : - visu I{liste les fichiers filtrés} - visusimple I{noms seulement} - copie I{copie sur répertoire de destinations} - supprime I{suppression} - azip I{crée un nouveau zip} - uzip I{update un zip} orep a également quelques propriétés : - dirbase nom simple du répertoire "de base" - ffic liste des fichiers filtrés - lfic liste de tous les fichiers - afic distionnaire contenant date/heure et taille des fichiers (indexé sur leur nom court) - sousrep liste des sous-répertoires (non récursif) - disk nom du disque - path path du répertoire (sans le disque, se termine toujours par '\' - dest buffer du répertoire de destination Note sur 'Dest' (répertoire de destination) : - La propriété 'dest' est (re)-définie par les filtre 'cmpXXX", par l'action 'copie' - Dès lors, elle devient utilisable comme valeur par défaut. """ def __init__(self,dirbase=None,disk=None,path='\\',sousrep=[],freres=[]): """La création d'une instance orep admet une absence de paramètres. C'est alors le répertoire courant qui est retenu. @param dirbase: nom du répertoire de base @param disk: disque du répertoire de base ; 'C:' par défaut @param path: chemin du répertoire de base ; '\\' par défaut """ if dirbase is None: st=os.getcwd() if st[1]==':': self.disk=st[:2] lst=st.split('\\') self.dirbase=lst[-1] self.path=string.join(lst[:-1],'\\')[2:]+'\\' elif st.startswith('\\\\'): self.disk='' lst=st.split('\\') self.dirbase=lst[-1] self.path=string.join(lst[:-1],'\\')+'\\' else: if disk is None: self.disk,self.path,self.dirbase=orep.decomposepath(dirbase) else: self.disk=disk self.path=path self.dirbase=dirbase if not self.path.endswith('\\'): self.path=self.path+'\\' if self.dirbase.endswith('\\'): self.dirbase=self.dirbase[:-1] lfic=os.listdir(unicode(self.disk+self.path+self.dirbase)) self.dest=self.disk+self.path+self.dirbase+'\\' self.sousrep=sousrep self.lfic=[] self.afic={} for sst in lfic: nomlong=self.disk+self.path+self.dirbase+'\\'+sst nomlong=os.path.join(self.disk,self.path,self.dirbase,sst) if os.path.isdir(nomlong): #if sousrep!=[]: self.sousrep.append(sst) else: self.lfic.append(sst) stat1=os.stat(nomlong) self.afic[sst]=[stat1[8],stat1[6]] self.lfic.sort() self.ffic=self.lfic #-------------------- Filtre -------------------------- def filtre(self): """ Annule les filtres (réinitialise) ; ffic contient ensuite tous les fichiers """ self.ffic=self.lfic def filtreext(self,*param): """ Filtre sur les extensions (casse ignorée) Exemple:: ob.filtreext('txt','ttt') @param param: des extension """ templst=[] filtrext=[] for i in param: if i.startswith('.'): filtrext.append(i.upper()) else: filtrext.append('.'+i.upper()) for f in self.ffic: ext=f[f.rfind('.'):] if (ext.upper() in filtrext) or filtrext=='*': templst.append(f) self.ffic=templst def filtredebut(self,*param): """ Filtre sur le début de nom des fichiers (casse ignorée) Exemple:: ob.filtredebut('form','rep','img') @param param: des chaînes de début de nom """ templst=[] sfiltre=[] for i in param: sfiltre.append(i.upper()) for f in self.ffic: for beg in sfiltre: if f.upper().startswith(beg): templst.append(f) self.ffic=templst def filtredatebasse(self,annee=2005,mois=1,jour=1,heure=0,minute=0,seconde=0): """ Filtre sur la date/heure basse ; seuls les fichiers postérieurs sont gardés Exemple:: oe.filtredatebasse(2003, 12, 31) """ templst=[] dd=time.mktime((annee,mois,jour,heure,minute,seconde,0,0,1)) for f in self.ffic: dat=self.afic[f][0] if dat>=dd : templst.append(f) self.ffic=templst def filtredatehaute(self,annee=2005,mois=1,jour=1,heure=23,minute=59,seconde=59): """ Filtre sur la date/heure haute ; seuls les fichiers antérieurs sont gardés Exemple:: oe.filtredatehaute(2005, 5, 31) """ templst=[] dd=time.mktime((annee,mois,jour,heure,minute,seconde,0,0,1)) for f in self.ffic: dat=self.afic[f][0] if dat<=dd : templst.append(f) self.ffic=templst def filtrere(self,pattern=r"^.+", casse="NON"): """ Filtre les fichiers, par une expression relationnelle, appliquée aux noms de le liste des fichiers Attn : la casse est ignorée par défaut. @param pattern: l'expression relationnelle ; le "motif" (pattern) @param casse: casse gérée (NON par défaut) """ templst=[] if casse=="NON": pat=re.compile(pattern,re.IGNORECASE) else: pat=re.compile(pattern) for f in self.ffic: if pat.search(f): templst.append(f) self.ffic=templst def filtretaille(self,taibasse=0,taihaute=999999999999999): """ Filtre sur la taille ; seuls les fichiers compris entre les deux tailles sont gardés Exemples:: oe.filtretaille(100000) # filtre sur les fichiers > 100 000 octets oe.filtretaille(0,1440000) # filtre sur les fichiers <1,44 Mo """ templst=[] #cf anti for f in self.ffic: tai=self.afic[f][1] if tai>=taibasse and tai<=taihaute: templst.append(f) self.ffic=templst def filtrenb(self,debut=None,fin=None): """ Extrait une partie des fichiers (utile surtout après un tri) Exemples:: oe.tridate() oe.filtrenb(-7,None) # garde les 7 fichiers les plus récents oe.filtreanti() # inversion du filtre (=> tous les fichiers, sauf les 7 plus récents) oe.supprime() # on a supprimé tous les fichiers autres que les 7 plus récents @param debut: position de début (dans la liste filtrée) @param fin: position de fin (dans la liste filtrée) """ if debut is None: if not(fin is None): self.ffic=self.ffic[:fin] else: if fin is None: self.ffic=self.ffic[debut:] else: self.ffic=self.ffic[debut:fin] def filtreanti(self): """ Inverse le filtre, relativement à la liste complète des fichiers. Après exécution, 'ffic' contient la liste des fichiers qui n'étaient pas dans le filtre, lors de l'appel à 'filtreanti'. """ templst=[] for f in self.lfic: if not f in self.ffic: templst.append(f) self.ffic=templst def cmpnom(self,odest=None): """ Fichiers qui n'existent pas dans odest : """ if odest is None: odest=self.dest else: self.dest=odest templst=[] for f in self.ffic: if not (f in odest.ffic) : templst.append(f) self.ffic=templst def cmpdt(self,odest=None): """ Fichiers qui, diffèrent, entre le répertoire de base et de destination. Critères de différence : - n'existent pas, - qui sont plus anciens (+ de 2 secondes), - dont la taille diffère """ if odest is None: odest=self.dest else: self.dest=odest.disk+odest.path+odest.dirbase+"\\" templst=[] for f in self.ffic: if not (f in odest.ffic) : templst.append(f) else: if ((self.afic[f][0]-odest.afic[f][0])>2) or (self.afic[f][1]!=odest.afic[f][1]) : templst.append(f) self.ffic=templst def cmpdiff(self, odest=None): """ Filtre (ne conserve) que les fichiers qui diffèrent, entre le répertoire de base et de destination. Critères de différence : - n'existent pas, - qui sont plus anciens (+ de 2 secondes), - dont la taille diffère @param: odest peut être soit une instance de orep, soit un path """ if odest is None: odest=self.dest else: if not isinstance(odest,orep): odest=orep(odest) self.dest=odest.disk+odest.path+odest.dirbase+"\\" templst=[] for f in self.ffic: if not (f in odest.ffic) : self.afic[f].append('+') templst.append(f) else: if (abs(self.afic[f][0]-odest.afic[f][0])>2) : self.afic[f].append('DateTime') templst.append(f) if (self.afic[f][1]!=odest.afic[f][1]) : self.afic[f].append('Taille') templst.append(f) self.ffic=templst return len(templst) #-------------------- Tri -------------------------- def trinom(self): """ Tri sur le nom des fichiers """ self.ffic.sort() def tridate(self): """ Tri sur la date/heure des fichiers """ templst=[] for f in self.ffic: templst.append([self.afic[f][0],f]) templst.sort() self.ffic=[] for f in templst: #print f self.ffic.append(f[1]) def tritaille(self): """ Tri sur la taille des fichiers """ templst=[] for f in self.ffic: templst.append([self.afic[f][1],f]) templst.sort() self.ffic=[] for f in templst: #print f self.ffic.append(f[1]) #-------------------- Action -------------------------- def visu(self): """ Visualise la liste des fichiers filtrés (nom fichier + date/heure + taille) """ print "disk",self.disk print "path",self.path print "dirbase",self.dirbase print #for i in self.ffic: # print i, #print #print for f in self.ffic: if len(self.afic[f])>2: cause=self.afic[f][2] else: cause='' #print f,' \t',time.strftime("%d.%m.%y %H:%M:%S",time.gmtime(self.afic[f][0])),' \t',self.afic[f][1],' \t',cause print f.encode('cp1252','replace').ljust(20),time.strftime("%d.%m.%y %H:%M:%S",time.gmtime(self.afic[f][0])),\ str(self.afic[f][1]).rjust(10),' ',cause def visusimple(self): """ Visualise la liste des fichiers filtrés (simplement le nom des fichiers) """ print for i in self.ffic: print i.encode('cp1252','replace') print def copie(self,repdest=None, delai=0.01): """ Copie les fichiers filtrés dans le répertoire de destination """ if repdest is None: repdest=self.dest else: self.dest=repdest rdest=repdest if (rdest[-1]!='\\'): rdest+='\\' if not os.path.exists(rdest[:-1]): os.makedirs(rdest[:-1]) st='' for f in self.ffic: #print 'orep.Copie ', #print u''+self.disk+self.path+self.dirbase+'\\'+f.decode('cp1252')+' ==> '+rdest+f.decode('cp1252') st+= u'Copie '+self.disk+self.path+self.dirbase.decode('cp1252')+'\\'+f.encode('cp1252','replace')+" ==> "+rdest.decode('cp1252')+f.encode('cp1252','replace') try: shutil.copyfile(os.path.join(self.disk,self.path,self.dirbase,f),os.path.join(rdest,f)) shutil.copystat(os.path.join(self.disk,self.path,self.dirbase,f),os.path.join(rdest,f)) except: time.sleep(1) #print "PROBLEME avec : ",os.path.join(self.disk,self.path,self.dirbase,f) pass time.sleep(delai) st+=u' Ok.\r\n' #print st.encode('cp850','replace') return st def supprime(self): """ Supprime les fichiers filtrés """ for f in self.ffic: os.remove(os.path.join(self.disk,self.path,self.dirbase,f)) def azip(self,nomfichierzip=None): """ Ajoute les fichiers filtrés, dans un NOUVEAU fichier zip @param nomfichierzip: nom du fichier zip (exemple : toto.zip) ; si absent, on prend le nom du répertoire + '.zip' """ import zipmci if nomfichierzip is None: nomfichierzip=self.dirbase+'.zip' os.chdir(self.disk+self.path+self.dirbase) if os.path.isfile(self.disk+self.path+self.dirbase+'\\'+nomfichierzip): os.remove(self.disk+self.path+self.dirbase+'\\'+nomfichierzip) zipmci.zipappend(nomfichierzip,[''],self.ffic) def uzip(self,nomfichierzip=None): """ Met à jour (update) les fichiers filtrés, dans le fichier zip @param nomfichierzip: nom du fichier zip (exemple : toto.zip) ; si absent, on prend le nom du répertoire + '.zip' """ import zipmci if nomfichierzip is None: nomfichierzip=self.dirbase+'.zip' os.chdir(self.disk+self.path+self.dirbase) zipmci.zipupdate(nomfichierzip,[''],self.ffic) def taille(self,nomfichierzip=None): """ Met à jour (update) les fichiers filtrés, dans le fichier zip @param nomfichierzip: nom du fichier zip (exemple : toto.zip) ; si absent, on prend le nom du répertoire + '.zip' """ taille=0 for f in self.ffic: taille+=self.afic[f][1] return taille @staticmethod def decomposepath(fichiercomplet): drive,ttmp=os.path.splitdrive(fichiercomplet) chemin,fichier=os.path.split(ttmp) #print drive, chemin, fichier return drive, chemin, fichier class srep(object): """ La Classe 'srep' collationne l'ensemble des sous-répertoires d'un emplacement donné srep a quelques propriétés : - dirbase nom simple du répertoire "de base" - srep liste des sous-répertoires (récursif) - disk nom du disque - path path du répertoire (sans le disque, se termine toujours par '\' """ def __init__(self, disk=None, dirbase=None, includedirbase=False): """La création d'une instance orep admet une absence de paramètres. C'est alors le répertoire courant qui est retenu. @param dirbase: nom du répertoire de base @param disk: disque du répertoire de base ; ou chemin complet """ if dirbase is None: if disk is None: st=os.getcwd() else: st=disk if st[1]==':': self.disk=st[:2] self.dirbase=st[2:] elif st.startswith('\\\\'): self.disk='' self.dirbase=st else: self.disk=disk self.dirbase=dirbase if self.dirbase.endswith('\\'): self.dirbase=self.dirbase[:-1] self.fdir=[] def chargefichiers(arg,rep,fichiers): disk=arg[0] prefix=arg[1] lrep=rep[len(disk+prefix):] #print "rep",rep if lrep=='' and includedirbase: lprefix=prefix.split('\\') self.fdir.append(orep(os.path.split(prefix)[1], disk, os.path.split(prefix)[0])) else: if lrep.startswith('\\'): lrep=lrep[1:] if lrep!='' or includedirbase: self.fdir.append(orep(lrep, disk, prefix)) os.path.walk(self.disk+self.dirbase, chargefichiers, (self.disk,self.dirbase)) self.ddir={} for d in self.fdir: self.ddir[d.dirbase]=d def chaque(self, filtre=None): for r in self.fdir: print r.disk+r.path+r.dirbase, r.taille() def cmpdiff(self, odest=None): """ Répertoires qui manquent ou sont en plus @param: odest peut être soit une instance de srep, soit un path """ if odest is None: odest=os.getcwd() if not isinstance(odest,srep): if odest.endswith('\\'): odest=self.dirbase[:-1] odest=srep(odest) plus=[] for i in self.ddir.keys(): if not odest.ddir.has_key(i): plus.append(i) moins=[] for i in odest.ddir.keys(): if not self.ddir.has_key(i): moins.append(i) plus.sort() moins.sort() return plus,moins def cmpidem(self, odest=None): """ Répertoires qui sont dans les deux endroits @param: odest peut être soit une instance de srep, soit un path """ if odest is None: odest=os.getcwd() if not isinstance(odest,srep): if odest.endswith('\\'): odest=self.dirbase[:-1] odest=srep(odest) egal=[] for i in self.ddir.keys(): if odest.ddir.has_key(i): egal.append(i) egal.sort() return egal def copydirs(self, ldir, rdest, delai=0.01): if (rdest[-1]!='\\'): rdest+='\\' lfret=[] for r in ldir: #print "Cree/Copie(dir):",rdest+r.decode('cp1252') if not os.path.exists(rdest+r.decode('cp1252')): os.makedirs(rdest+r) listefic=os.listdir(self.disk+'\\'+self.dirbase+'\\'+r) for f in listefic: if not os.path.isdir(self.disk+self.dirbase+'\\'+r+'\\'+f): try: shutil.copyfile(os.path.join(self.disk,self.dirbase,r,f),os.path.join(rdest,r,f)) shutil.copystat(os.path.join(self.disk,self.dirbase,r,f),os.path.join(rdest,r,f)) except: time.sleep(1) #print "PROBLEME avec ",self.disk+self.dirbase+'\\'+r+'\\'+f.decode('cp1252') pass lfret.append(os.path.join(self.disk,self.dirbase,r,f)) time.sleep(delai) return lfret if __name__=='__main__': """ rep=srep('D:','\\Dev\\Python') for r in rep.fdir: print r.disk, r.path, r.dirbase #rep.chaque() """ """ rb=srep('C:','\\temp') r2=srep('C:','\\temp2') p,m=rb.cmpdiff(r2) print '-'*71 print "Répertoires en Plus" print '\r\n'.join(p) print print '-'*71 print "Répertoires en Moins" print '\r\n'.join(m) print '-'*71 print for r in rb.cmpidem(r2): o=rb.ddir[r] o2=r2.ddir[r] if o.cmpdiff(o2)>0: print "*"*49 o.visu() print "*"*49 """ def Exemple_1(): """ Exemple 1 - Définit le répertoire C{C:\\Test\\Org} - Sélectionne les fichiers C{*.txt *.ttt} - Sélectionne les fichiers entre le 01.01.2005 et le 31.03.2005 - Tri le résultat par dates - L'affiche. :: rep=orep.orep('Org','C:','\\Test') rep.filtreext('txt','ttt') rep.filtredatebasse(2005, 1, 1) rep.filtredatehaute(2001, 3, 31) rep.tridate() rep.visu() """ def Exemple_2(): """ Exemple 2 - Définit le répertoire C{C:\\Test\\Org} - Sélectionne les fichiers C{*.fsl *.rsl} - Met à jour le fichier FicRep.zip - Copie les fichiers .zip sur \\Serveur\sauve :: rep=orep.orep('Org','C:','\\Test') rep.filtreext('fsl','rsl') rep.uzip("FicRep.zip") rep.filtre() rep.filtreext('zip') rep.copie(r'\\Serveur\sauve') """ def Exemple_3(): """ Exemple 3 - Définit le répertoire C{C:\\Test\\Org} - Sélectionne les fichiers C{*.fsl *.rsl} - Définit un répertoire de comparaison C{D:\\Archiv} - Y copie les fichiers (fsl/rsl) différents :: rep=orep.orep('Org','C:','\\Test') rep.filtreext('fsl','rsl') r2=orep.orep('Archiv','D:','\\') r2.filtreext('fsl','rsl') rep.cmpdiff(r2) rep.copie() """ def Exemple_4(): """ Exemple 4 - Définit le répertoire C{C:\\temp} - Sélectionne les fichiers C{*.txt} - Définit un répertoire de comparaison C{C:\\temp2} - Y copie les fichiers (fsl/rsl) différents """ rep=orep('temp','C:','') rep.filtreext('txt') r2=orep('temp2','C:','') r2.filtreext('txt') rep.cmpdiff(r2) rep.visu() rep.copie() Exemple_4()