Python-Listenverzeichnis, Unterverzeichnis und Dateien

130

Ich versuche, ein Skript zu erstellen, um alle Verzeichnisse, Unterverzeichnisse und Dateien in einem bestimmten Verzeichnis aufzulisten.
Ich habe es versucht:

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)

Leider funktioniert es nicht richtig.
Ich bekomme alle Dateien, aber nicht ihre vollständigen Pfade.

Zum Beispiel, wenn die dir-Struktur wäre:

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

Es würde drucken:

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

Was ich brauche, ist das erste Ergebnis. Jede Hilfe wäre sehr dankbar! Vielen Dank.

thomytheyon
quelle

Antworten:

225

Verwenden Sie os.path.joindie verketten Verzeichnis und Dateiname :

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

Beachten Sie die Verwendung von pathund nicht rootin der Verkettung, da die Verwendung rootfalsch wäre.


In Python 3.4 wurde das pathlib- Modul hinzugefügt , um die Pfadmanipulation zu vereinfachen. Das Äquivalent zu os.path.joinwäre also:

pathlib.PurePath(path, name)

Der Vorteil von pathlibist, dass Sie eine Vielzahl nützlicher Methoden für Pfade verwenden können. Wenn Sie die konkrete PathVariante verwenden, können Sie auch tatsächliche Betriebssystemaufrufe über sie ausführen, z. B. in ein Verzeichnis wechseln, den Pfad löschen, die Datei öffnen, auf die er verweist, und vieles mehr.

Eli Bendersky
quelle
Dies ist die einzige nützliche Antwort auf die vielen Fragen, die gestellt wurden: "Wie werden alle Dateien rekursiv in Python abgerufen?".
Harrisonfooord
Verständnisliste: all_files = [os.path.join (Pfad, Name) für Name in Dateien für Pfad, Unterverzeichnisse, Dateien in os.walk (Ordner)]
Nir
45

Nur für den Fall ... Alle Dateien im Verzeichnis und in den Unterverzeichnissen, die einem bestimmten Muster entsprechen (z. B. * .py):

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)
Ivan
quelle
10

Hier ist ein Einzeiler:

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

Die äußerste val for sublist in ...Schleife glättet die Liste eindimensional. Die jSchleife sammelt eine Liste aller Dateibasennamen und verknüpft sie mit dem aktuellen Pfad. Schließlich idurchläuft die Schleife alle Verzeichnisse und Unterverzeichnisse.

In diesem Beispiel wird der fest codierte Pfad ./im os.walk(...)Aufruf verwendet. Sie können eine beliebige Pfadzeichenfolge ergänzen.

Hinweis: os.path.expanduserund / oder os.path.expandvarskann für Pfadzeichenfolgen wie verwendet werden~/

Dieses Beispiel erweitern:

Es ist einfach, in Dateibasennamen-Tests und Verzeichnisnamen-Tests hinzuzufügen.

Beispiel: Testen auf *.jpgDateien:

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

Zusätzlich ohne das .gitVerzeichnis:

... for i in os.walk('./') if '.git' not in i[0].split('/')]
ThorSummoner
quelle
Es funktioniert, aber um .git directoy auszuschließen, müssen Sie überprüfen, ob '.git' NICHT im Pfad enthalten ist.
Roman Rdgz
Ja. Sollte sein, wenn '.git' nicht in i [0] .split ('/')]
Roman Rdgz
Ich würde os.walküber eine manuelle Dirlisting-Schleife empfehlen , Generatoren sind großartig, verwenden Sie sie.
ThorSummoner
9

Konnte hier keine Antwort schreiben. Dies ist die klarste Zeile, die ich je gesehen habe:

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

Sie können sich dieses Beispiel ansehen, das ich gemacht habe. Es verwendet die Funktion os.path.walk, die veraltet ist. Vorsicht. Verwendet eine Liste zum Speichern aller Dateipfade

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)
devsaw
quelle
4

Ein bisschen einfacher Einzeiler:

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)])
Daniel
quelle
2

Da jedes Beispiel hier nur walk(mit join) verwendet, möchte ich ein schönes Beispiel und einen Vergleich zeigen mit 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

Wie Sie selbst sehen können, ist die listdirVersion viel effizienter. (und das joinist langsam)

Pfütze
quelle