2017-10-19 5 views
2

Je suis en train d'essayer de parcourir les fichiers dans un répertoire et de trouver des doublons et de les supprimer. J'ai 29 000 fichiers dans le répertoire donc faire une force brutale prendra plus d'un jour.Python Loop à partir du fichier actuel

J'ai les noms de fichiers qui sont comme suit:

« some_file_name » « un-fichier-name »

donc un nom a underscores et l'autre a des traits et parfois ils sont 2 ou trois points une part.

Alors, comment faire pour que ma boucle interne commence à la position de la boucle externe dans le répertoire et qu'elle ne vérifie que les 10 prochaines?

Voici Brute code vigueur:

import glob, os 
os.chdir("C:/Dir/dir") 

for file in glob.glob("*"): 
    temp = file 
    temp = temp.replace("-", " ") 
    temp = temp.replace("_", " ") 

#How do I start this loop where file is currently at and continue for the next 10 files 
for file2 in glob.glob("*"): 
    temp2 = file2 
    temp2 = temp2.replace("-", " ") 
    temp2 = temp2.replace("_", " ") 
    if temp == temp2: 
     os.remove(file2) 
+0

Voulez-vous des trouver des doublons en fonction du contenu ou de la même nom seul? – Tomalak

+0

Plutôt que de boucler deux fois (temp1 et temp2) avez-vous essayé d'utiliser une structure de données (un ensemble ou une liste) pour garder trace des noms de fichiers que vous avez déjà visités? De cette façon, vous n'avez besoin de faire une boucle qu'une seule fois sur chaque fichier. – pills

Répondre

3

D'après ce que je comprends votre question, vous voulez supprimer des fichiers de même nom à partir d'un répertoire. Je pense que votre approche ("regardez les 10 prochains noms de fichiers") est trop imprécise et trop compliquée.

La condition est, lorsque les deux un fichier some_file_name et un fichier some-file-name existent, supprimez l'un d'entre eux. Ceci peut être fait très facilement en construisant une liste de noms de fichiers et pour chaque entrée, vérifiez si un nom de fichier avec des traits de soulignement au lieu de tirets existe aussi et si c'est le cas, supprimez-le. Pour ce faire, utilisez un set, car les ensembles ont de très bonnes caractéristiques de recherche, par exemple, some_value in some_set est beaucoup plus rapide qu'avec les listes. Il évite également les vérifications excessives des fichiers existants (comme l'appel os.path.isfile(file)), puisque nous connaissons déjà tous les fichiers qui existent à partir de la construction de l'ensemble.

import glob, os 

filenames = {file for file in glob.glob(r"C:\Dir\dir\*")} 

for file in filenames: 
    delete_candidate = file.replace("-", "_") 
    if delete_candidate != file and delete_candidate in filenames: 
     os.remove(delete_candidate) 
     print("deleted " + delete_candidate) 

{x for x in iterable} est une compréhension de jeu , il construit un ensemble à partir d'une liste de valeurs. Cela fonctionne exactement comme les listes de compréhension.

+0

Utilisez '{}' pour définir la compréhension, vous avez créé un générateur – Uriel

+0

D'oh. Bien sûr. – Tomalak

+0

Merci, je me sens un peu bête maintenant. C'est en fait une solution très simple, merci néanmoins, ça marche! – user3918910

0

Vous pouvez utiliser un dictionnaire et mettre le « nom simple » (sans _ ou -) comme la clé et tous les noms de fichiers réels valeurs:

import glob, os 

def extendDictValue(dDict, sKey, uValue): 
    if sKey in dDict: 
     dDict[sKey].append(uValue) 
    else: 
     dDict[sKey] = [uValue] 


os.chdir("C:/Dir/dir") 
filenames_dict = {} 
for filename in glob.glob("*"): 
    simple_name = filename.replace("-", " ").replace("_", " ") 
    extendDictValue(filenames_dict, simple_name, filename) 

for simple_name, filenames in filenames_dict.items(): 
    if len(filenames) > 1: 
     filenames.pop(0) 
     for filename in filenames: 
      os.remove(filename)