2009-11-09 6 views
1

Supposons que je ces dossiersmanipulation de fichiers Python

rootfolder 
     | 
    /\ \ 
    01 02 03 .... 
    | 
    13_itemname.xml 

donc sous mon RootFolder, chaque répertoire représente un mois comme 01 02 03 et dans ces répertoires que j'ai des articles avec leur création heure et le nom article tels que 16_item1 .xml, 24_item1.xml etc, comme vous pouvez le deviner il y a plusieurs éléments et chaque xml créé toutes les heures.

Maintenant, je veux faire deux choses:

  • J'ai besoin de générer une liste de noms de poste pour un mois, soit pour 01 je Item1, item2 et ITEM3 à l'intérieur.

  • J'ai besoin de filtrer chaque élément, comme pour item1: je veux lire chacun de 01_item1.xml à 24_item1.xml.

Comment puis-je les atteindre facilement en Python?

+0

Quel code avez-vous maintenant? Ce n'est pas "écrire mon code pour moi.com". Qu'avez-vous essayé? Quand vous avez regardé 'os.walk', qu'avez-vous vu? –

Répondre

5

Voici deux méthodes de faire ce que vous demandez (si je l'ai bien compris). Un avec regex, un sans. Vous choisissez celui que vous préférez;)

Un bit qui peut sembler magique est la ligne "setdefault". Pour une explication, voir the docs. Je laisse comme « un exercice au lecteur » pour comprendre comment il fonctionne;)

from os import listdir 
from os.path import join 

DATA_ROOT = "testdata" 

def folder_items_no_regex(month_name): 

    # dict holding the items (assuming ordering is irrelevant) 
    items = {} 

    # 1. Loop through all filenames in said folder 
    for file in listdir(join(DATA_ROOT, month_name)): 
     date, name = file.split("_", 1) 

     # skip files that were not possible to split on "_" 
     if not date or not name: 
     continue 

     # ignore non-.xml files 
     if not name.endswith(".xml"): 
     continue 

     # cut off the ".xml" extension 
     name = name[0:-4] 

     # keep a list of filenames 
     items.setdefault(name, set()).add(file) 

    return items 

def folder_items_regex(month_name): 

    import re 

    # The pattern: 
    # 1. match the beginnning of line "^" 
    # 2. capture 1 or more digits (\d+) 
    # 3. match the "_" 
    # 4. capture any character (as few as possible): (.*?) 
    # 5. match ".xml" 
    # 6. match the end of line "$" 
    pattern = re.compile(r"^(\d+)_(.*?)\.xml$") 

    # dict holding the items (assuming ordering is irrelevant) 
    items = {} 

    # 1. Loop through all filenames in said folder 
    for file in listdir(join(DATA_ROOT, month_name)): 

     match = pattern.match(file) 
     if not match: 
     continue 

     date, name = match.groups() 

     # keep a list of filenames 
     items.setdefault(name, set()).add(file) 

    return items 
if __name__ == "__main__": 
    from pprint import pprint 

    data = folder_items_no_regex("02") 

    print "--- The dict ---------------" 
    pprint(data) 

    print "--- The items --------------" 
    pprint(sorted(data.keys())) 

    print "--- The files for item1 ---- " 
    pprint(sorted(data["item1"])) 


    data = folder_items_regex("02") 

    print "--- The dict ---------------" 
    pprint(data) 

    print "--- The items --------------" 
    pprint(sorted(data.keys())) 

    print "--- The files for item1 ---- " 
    pprint(sorted(data["item1"])) 
+0

merci beaucoup pour le code! – Hellnar

+0

De rien. Je viens de l'éditer légèrement. Regarde. Il peut être moins lisible, mais il peut fonctionner mieux (juste un instinct). – exhuma

+0

* Très important *: Le code ci-dessus contenait un bug. Si le nom de l'article contenait un "_", le code romprait avec "trop ​​de valeurs à décompresser" (je pense que c'est le message que cela donnerait). J'ai ajouté un paramètre "maxsplit" à l'appel de "split". Cela permettra d'éviter l'erreur. – exhuma

0

En supposant que les noms des éléments ont un préfixe de longueur fixe et le suffixe (c.-à-un préfixe de 3 caractères tels que « 01_ » et 4 suffixe de caractère « .xml »), vous pouvez résoudre la première partie du problème comme celui-ci:

names = set(name[3:-4] for name in os.listdir('01') if name.endswith('.xml')] 

que vous obtiendrez les noms des éléments uniques.

Pour filtrer chaque élément, recherchez simplement les fichiers qui se terminent par le nom de cet élément et triez-le si nécessaire.

item_suffix = '_item2.xml' 
filtered = sorted(name for name in os.listdir('01') if name.endswith(item_suffix)) 
0

Je ne sais pas exactement ce que vous voulez faire, mais voici quelques conseils qui pourraient être utiles


créer des noms de fichiers (« % 02d » signifie la jambière gauche avec des zéros)

foldernames = ["%02d"%i for i in range(1,13)]

filenames = ["%02d"%i for i in range(1,24)]


utilisation os.path.join pour la construction de chemins complexes au lieu de concaténation de chaînes

os.path.join(foldername,filename) 

os.path.existe pour vérifier si un fichier existe d'abord

if os.path.exists(newname): 
    print "file already exists" 

pour la liste du contenu du répertoire, utilisez glob

from glob import glob 
xmlfiles = glob("*.xml") 

utilisation shutil pour les opérations de niveau supérieur comme la création de dossiers, renommer les fichiers

shutil.move(oldname,newname)


basename pour obtenir un nom de fichier à partir d'un chemin complet

filename = os.path.basename(fullpath)