web-dev-qa-db-fra.com

Répertoire de liste, sous-répertoire et fichiers Python

J'essaie de créer un script pour répertorier tous les répertoires, sous-répertoires et fichiers d'un répertoire donné.
J'ai essayé ceci:

import sys,os

root = "/home/patate/directory/"
path = os.path.join(root, "targetdirectory")

for r,d,f in os.walk(path):
    for file in f:
        print os.path.join(root,file)

Malheureusement, cela ne fonctionne pas correctement.
Je récupère tous les fichiers, mais pas leur chemin complet.

Par exemple, si la structure dir est:

/home/patate/directory/targetdirectory/123/456/789/file.txt 

Il imprimerait:

/home/patate/directory/targetdirectory/file.txt 

Ce dont j'ai besoin, c'est le premier résultat. Toute aide serait grandement appréciée! Merci.

87
thomytheyon

Utilisez os.path.join pour concaténer le répertoire et le fichier nom:

for path, subdirs, files in os.walk(root):
    for name in files:
        print os.path.join(path, name)

Notez l'utilisation de path et non root dans la concaténation, car utiliser root serait incorrect.


Dans Python 3.4, le module pathlib a été ajouté pour faciliter les manipulations de chemin. Donc l'équivalent de os.path.join serait:

pathlib.PurePath(path, name)

L’avantage de pathlib est que vous pouvez utiliser diverses méthodes utiles sur les chemins. Si vous utilisez la variante concrète Path, vous pouvez également effectuer de véritables appels système, comme modifier un répertoire, supprimer le chemin, ouvrir le fichier indiqué, etc.

167
Eli Bendersky

Juste au cas où ... Obtenir tous les fichiers du répertoire et des sous-répertoires correspondant à un modèle (* .py par exemple):

import os
from fnmatch import fnmatch

root = '/some/directory'
pattern = "*.py"

for path, subdirs, files in os.walk(root):
    for name in files:
        if fnmatch(name, pattern):
            print os.path.join(path, name)
27
Ivan

Voici un one-liner:

import os

[val for sublist in [[os.path.join(i[0], j) for j in i[2]] for i in os.walk('./')] for val in sublist]
# Meta comment to ease selecting text

La boucle la plus externe val for sublist in ... aplatit la liste pour qu'elle soit unidimensionnelle. La boucle j collecte une liste de chaque nom de base de fichier et la joint au chemin actuel. Enfin, la boucle i parcourt tous les répertoires et sous-répertoires.

Cet exemple utilise le chemin d'accès codé en dur ./ dans l'appel os.walk(...) , vous pouvez compléter n'importe quelle chaîne de chemin d'accès de votre choix.

Remarque: os.path.expanduser et/ou os.path.expandvars peut être utilisé pour les chaînes de chemin d'accès telles que ~/

Prolonger cet exemple:

Il est facile d’ajouter des tests de nom de fichier et de nom de répertoire. 

Par exemple, testez les fichiers *.jpg:

... for j in i[2] if j.endswith('.jpg')] ...

De plus, à l'exclusion du répertoire .git:

... for i in os.walk('./') if '.git' not in i[0].split('/')]
7
ThorSummoner

Vous devriez utiliser 'r' dans votre jointure au lieu de 'root'

5
Trent

Je ne peux pas commenter, écrivez donc la réponse ici. C'est la ligne la plus claire que j'ai vue:

import os
[os.path.join(path, name) for path, subdirs, files in os.walk(root) for name in files]
3
Mong H. Ng

Vous pouvez jeter un oeil à cet échantillon que j'ai fait. Il utilise la fonction os.path.walk qui est déconseillée. Attention. Utilise une liste pour stocker tous les chemins de fichiers.

root = "Your root directory"
ex = ".txt"
where_to = "Wherever you wanna write your file to"
def fileWalker(ext,dirname,names):
    '''
    checks files in names'''
    pat = "*" + ext[0]
    for f in names:
        if fnmatch.fnmatch(f,pat):
            ext[1].append(os.path.join(dirname,f))


def writeTo(fList):

    with open(where_to,"w") as f:
        for di_r in fList:
            f.write(di_r + "\n")






if __== '__main__':
    li = []
    os.path.walk(root,fileWalker,[ex,li])

    writeTo(li)
1
devsaw

Un peu plus simple one-liner:

import os
from itertools import product, chain

chain.from_iterable([["\\".join(w) for w in product([i[0]], i[2])] for i in os.walk(dir)])
0
Daniel

Étant donné que chaque exemple utilisé ici utilise uniquement walk (avec join), j'aimerais montrer un exemple intéressant et une comparaison avec listdir:

import os, time

def listFiles1(root): # listdir
    allFiles = []; walk = [root]
    while walk:
        folder = walk.pop(0)+"/"; items = os.listdir(folder) # items = folders + files
        for i in items: i=folder+i; (walk if os.path.isdir(i) else allFiles).append(i)
    return allFiles

def listFiles2(root): # listdir/join (takes ~1.4x as long) (and uses '\\' instead)
    allFiles = []; walk = [root]
    while walk:
        folder = walk.pop(0); items = os.listdir(folder) # items = folders + files
        for i in items: i=os.path.join(folder,i); (walk if os.path.isdir(i) else allFiles).append(i)
    return allFiles

def listFiles3(root): # walk (takes ~1.5x as long)
    allFiles = []
    for folder, folders, files in os.walk(root):
        for file in files: allFiles+=[folder.replace("\\","/")+"/"+file] # folder+"\\"+file still ~1.5x
    return allFiles

def listFiles4(root): # walk/join (takes ~1.6x as long) (and uses '\\' instead)
    allFiles = []
    for folder, folders, files in os.walk(root):
        for file in files: allFiles+=[os.path.join(folder,file)]
    return allFiles


for i in range(100): files = listFiles1("src") # warm up

start = time.time()
for i in range(100): files = listFiles1("src") # listdir
print("Time taken: %.2fs"%(time.time()-start)) # 0.28s

start = time.time()
for i in range(100): files = listFiles2("src") # listdir and join
print("Time taken: %.2fs"%(time.time()-start)) # 0.38s

start = time.time()
for i in range(100): files = listFiles3("src") # walk
print("Time taken: %.2fs"%(time.time()-start)) # 0.42s

start = time.time()
for i in range(100): files = listFiles4("src") # walk and join
print("Time taken: %.2fs"%(time.time()-start)) # 0.47s

Comme vous pouvez le constater, la version listdir est beaucoup plus efficace. (et que join est lent)

0
Puddle