Directory dell'elenco Python, sottodirectory e file


130

Sto cercando di creare uno script per elencare tutte le directory, le sottodirectory e i file in una determinata directory.
Ho provato questo:

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)

Sfortunatamente non funziona correttamente.
Ottengo tutti i file, ma non i loro percorsi completi.

Ad esempio se la dir struct sarebbe:

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

Stampa:

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

Quello di cui ho bisogno è il primo risultato. Qualsiasi aiuto sarebbe molto apprezzato! Grazie.

Risposte:


225

Utilizzare os.path.joinper concatenare la directory e il nome del file :

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

Nota l'uso di pathe non rootnella concatenazione, poiché l'utilizzo rootsarebbe errato.


In Python 3.4 è stato aggiunto il modulo pathlib per manipolazioni del percorso più semplici. Quindi l'equivalente os.path.joinsarebbe:

pathlib.PurePath(path, name)

Il vantaggio pathlibè che è possibile utilizzare una varietà di metodi utili sui percorsi. Se utilizzi la Pathvariante concreta , puoi anche effettuare chiamate del sistema operativo reale attraverso di esse, come cambiare in una directory, eliminare il percorso, aprire il file a cui punta e molto altro.


questa è l'unica e unica risposta utile per le molte domande che sono state poste su "come ottenere ricorsivamente tutti i file in Python".
Harrisonfooord,

elenco di comprensione: all_files = [os.path.join (percorso, nome) per il nome nei file per percorso, sottodir, file in os.walk (cartella)]
Nir

45

Per ogni evenienza ... Ottenere tutti i file nella directory e le sottodirectory corrispondenti ad alcuni pattern (* .py per esempio):

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)

10

Ecco 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

Il val for sublist in ...ciclo più esterno appiattisce l'elenco in modo che sia monodimensionale. Il jciclo raccoglie un elenco di ogni nome file di base e lo unisce al percorso corrente. Infine, il iciclo scorre su tutte le directory e sottodirectory.

In questo esempio viene utilizzato il percorso hardcoded ./nella os.walk(...)chiamata, è possibile integrare qualsiasi stringa di percorso che ti piace.

Nota: os.path.expandusere / o os.path.expandvarspuò essere utilizzato per stringhe di percorsi come~/

Estensione di questo esempio:

È facile aggiungere test di nome file e test di directoryname.

Ad esempio, test per i *.jpgfile:

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

Inoltre, esclusa la .gitdirectory:

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

Funziona, ma per escludere .git direttamente devi controllare se '.git' NON è nel percorso.
Roman Rdgz,

Sì. Dovrebbe essere se '.git' non è in i [0] .split ('/')]
Roman Rdgz,

Consiglierei os.walksu un ciclo di dirlisting manuale, i generatori sono fantastici, vai ad usarli.
ThorSummoner il

9

Non posso commentare così scrivendo la risposta qui. Questa è la riga più chiara che abbia mai visto:

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

4

Puoi dare un'occhiata a questo campione che ho realizzato. Utilizza la funzione os.path.walk che è deprecata, attenzione. Utilizza un elenco per memorizzare tutti i percorsi dei file

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 __name__ == '__main__':
    li = []
    os.path.walk(root,fileWalker,[ex,li])

    writeTo(li)

4

One-liner un po 'più semplice:

import os
from itertools import product, chain

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

2

Poiché ogni esempio qui sta solo usando walk(con join), vorrei mostrare un bell'esempio e un confronto con 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

Come puoi vedere tu stesso, la listdirversione è molto più efficiente. (e questo joinè lento)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.