2009-08-15 3 views
1

J'ai un tas de fichiers dans un seul répertoire que je voudrais organiser dans les sous-répertoires.Copier des fichiers dans des répertoires comme spécifié dans une liste de fichiers avec python

Cette structure de répertoire (fichier qui irait dans quel répertoire) est spécifié dans une liste de fichiers qui ressemble à ceci:

Directory: Music\

-> 01-some_song1.mp3

-> 02-some_song2.mp3

-> 03-some_song3.mp3

Directory: Images\

-> 01-some_image1.jpg

-> 02-some_image2.jpg

......................

Je pensais à l'extraction des données (nom du répertoire et le nom du fichier) et le stocker dans un dictionnaire qui ressemblerait à ceci:

dictionary = {'Music': (01-some_song1.mp3, 02-some_song2.mp3, 
         03-some_song3.mp3), 
       'Images': (01-some_image1.jpg, 02-some_image2.jpg), 
      ...................................................... 
} 

Après cela, je voudrais copier/déplacer les fichiers dans leurs répertoires respectifs.

J'ai déjà extrait les noms de répertoire et créé les répertoires vides.

Pour les valeurs du dictionnaire j'ai essayé d'obtenir une liste de listes en procédant comme suit:

def get_values(file): 
    values = [] 
    tmp = [] 
    pattern = re.compile(r'^-> (.+?)$') 
    for line in file: 
     if line.strip().startswith('->'): 
      match = re.search(pattern, line.strip()) 
      if match: 
       tmp.append(match.group(1)) 
     elif line.strip().startswith('Directory'): 
      values.append(tmp) 
      del tmp[:] 
    return values 

Cela ne semble pas fonctionner. Chaque liste de la liste values contient les mêmes 4 noms de fichiers encore et encore.

Qu'est-ce que je fais mal?

J'aimerais aussi savoir quelles sont les autres façons de faire tout cela? Je suis sûr qu'il y a un moyen meilleur/plus simple/plus propre.

Répondre

1

pas nécessaire d'utiliser une expression régulière

d = {} 
for line in open("file"): 
    line=line.strip() 
    if line.endswith("\\"): 
     directory = line.split(":")[-1].strip().replace("\\","") 
     d.setdefault(directory,[]) 
    if line.startswith("->"): 
     song=line.split(" ")[-1] 
     d[directory].append(song) 
print d 

sortie

# python python.py 
{'Images': ['01-some_image1.jpg', '02-some_image2.jpg'], 'Music': ['01-some_song1.mp3', '02-some_song2.mp3', '03-some_song3.mp3']} 
+0

J'aime votre solution. C'est plus simple. Je n'ai pas pensé à le faire de cette façon. Le seul problème est que dans mon fichier, les noms de fichiers contiennent des espaces, donc je ne peux pas séparer l'espace. Je vais juste scinder ">" et utiliser strip() pour l'espace restant. Merci. –

1

Je pense que la cause est que vous réutilisez toujours la même liste.

del tmp[:] efface la liste et ne crée pas une nouvelle instance. Dans votre cas, vous devez créer une nouvelle liste en appelant tmp = []

Après correction devrait fonctionner (je ne pas testé)

 
def get_values(file): 
    values = [] 
    tmp = [] 
    pattern = re.compile(r'^-> (.+?)$') 
    for line in file: 
     if line.strip().startswith('->'): 
      match = re.search(pattern, line.strip()) 
      if match: 
       tmp.append(match.group(1)) 
     elif line.strip().startswith('Directory'): 
      values.append(tmp) 
      tmp = [] 
    return values 
+0

Il fonctionne. Merci. –

0

Si vous utilisez collections.defaultdict (liste), vous obtenez une liste qui dicti onary dont les éléments sont des listes. Si la clé n'est pas trouvée, elle est ajoutée avec une valeur de liste vide, de sorte que vous pouvez commencer à l'ajouter à la liste immédiatement.C'est ce que cette ligne fait:

d[dir].append(match.group(1)) 

Il crée le nom du répertoire comme une clé si elle n'existe pas et ajoute le nom de fichier trouvé à la liste. Par ailleurs, si vous rencontrez des problèmes pour utiliser vos expressions régulières, essayez de les créer avec l'indicateur de débogage. Je ne me rappelle pas le nom symbolique, mais le nombre est 128. Donc, si vous faites ceci:

file_regex = re.compile(r'^-> (.+?)$', 128) 

Vous obtenez cette sortie supplémentaire:

at at_beginning 
literal 45 
literal 62 
literal 32 
subpattern 1 
    min_repeat 1 65535 
    any None 
at at_end 

Et vous pouvez voir qu'il ya un début line match plus '->' (pour 45 62 32) et ensuite un motif répété et un résultat de fin de ligne. Très utile pour le débogage.

code:

from __future__ import with_statement 

import re 
import collections 

def get_values(file): 
    d = collections.defaultdict(list) 
    dir = "" 
    dir_regex = re.compile(r'^Directory: (.+?)\\$') 
    file_regex = re.compile(r'\-\> (.+?)$') 
    with open(file) as f: 
     for line in f: 
      line = line.strip() 
      match = dir_regex.search(line) 
      if match: 
       dir = match.group(1) 
      else: 
       match = file_regex.search(line) 
       if match: 
        d[dir].append(match.group(1)) 
    return d 

if __name__ == '__main__': 
    d = get_values('test_file') 
    for k, v in d.items(): 
     print k, v 

Résultat:

Images ['01-some_image1.jpg', '02-some_image2.jpg'] 
Music ['01-some_song1.mp3', '02-some_song2.mp3', '03-some_song3.mp3'] 
+0

Merci pour la réponse détaillée. Bien que je trouve la solution de ghostdog plus simple, votre réponse était tout aussi informative. Je vous remercie. –