Katalog listy Pythona, podkatalog i pliki

130

Próbuję stworzyć skrypt, który wyświetli listę wszystkich katalogów, podkatalogów i plików w podanym katalogu.
Próbowałem tego:

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)

Niestety nie działa poprawnie.
Dostaję wszystkie pliki, ale nie pełne ścieżki.

Na przykład, jeśli struktura dir byłaby:

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

Wypisze:

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

Potrzebuję pierwszego wyniku. Każda pomoc byłaby bardzo mile widziana! Dzięki.

thomytheyon
źródło

Odpowiedzi:

225

Służy os.path.joindo łączenia katalogu i nazwy pliku :

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

Zwróć uwagę na użycie pathi nie rootw konkatenacji, ponieważ użycie rootbyłoby nieprawidłowe.


W Pythonie 3.4 dodano moduł pathlib , aby ułatwić manipulowanie ścieżkami. Więc odpowiednikiem os.path.joinbyłoby:

pathlib.PurePath(path, name)

Zaletą pathlibjest to, że na ścieżkach można używać różnych przydatnych metod. Jeśli używasz konkretnego Pathwariantu, możesz również wykonywać za ich pośrednictwem rzeczywiste wywołania systemu operacyjnego, takie jak chodzenie do katalogu, usuwanie ścieżki, otwieranie pliku, na który wskazuje i wiele więcej.

Eli Bendersky
źródło
jest to jedyna użyteczna odpowiedź na wiele pytań dotyczących „jak uzyskać rekursywnie wszystkie pliki w Pythonie”.
harrisonfooord
listowego: all_files = [os.path.join (ścieżka, nazwa) dla nazwy w plikach na ścieżce, subdirs pliki w os.walk (folder)]
Nir
45

Na wszelki wypadek ... Pobieranie wszystkich plików w katalogu i podkatalogach pasujących do jakiegoś wzorca (na przykład * .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
źródło
10

Oto jedna linijka:

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

Najbardziej zewnętrzna val for sublist in ...pętla spłaszcza listę, aby była jednowymiarowa. jPętla pobiera listę wszystkich plików basename i dołącza je do bieżącej ścieżki. Na koniec ipętla iteruje po wszystkich katalogach i podkatalogach.

Ten przykład wykorzystuje zakodowaną ścieżkę ./w os.walk(...)wywołaniu, możesz uzupełnić dowolny ciąg ścieżki.

Uwaga: os.path.expanduseri / lub os.path.expandvarsmogą być używane dla ciągów ścieżek, takich jak~/

Rozszerzając ten przykład:

Łatwo jest dodać testy nazw plików i testy nazw katalogów.

Na przykład testowanie *.jpgplików:

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

Dodatkowo z wyłączeniem .gitkatalogu:

... for i in os.walk('./') if '.git' not in i[0].split('/')]
ThorSummoner
źródło
To działa, ale aby wykluczyć plik .git directoy, musisz sprawdzić, czy „.git” NIE znajduje się w ścieżce.
Roman Rdgz
Tak. Powinno być, jeśli „.git” nie znajduje się w i [0] .split („/”)]
Roman Rdgz
Polecam os.walkna ręczną pętlę dirlisting, generatory są świetne, przejdź z nich korzystać.
ThorSummoner
9

Nie udało się skomentować, więc piszę odpowiedź tutaj. Oto najbardziej przejrzysta jedna linia, jaką widziałem:

import os
[os.path.join(path, name) for path, subdirs, files in os.walk(root) for name in files]
Mong H. Ng
źródło
4

Możesz spojrzeć na tę próbkę, którą zrobiłem. Używa funkcji os.path.walk, która jest przestarzała, uważaj. Używa listy do przechowywania wszystkich ścieżek plików

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
źródło
4

Nieco prostsza jedna linijka:

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
źródło
2

Ponieważ każdy przykład tutaj używa tylko walk(z join), chciałbym pokazać ładny przykład i porównanie z 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

Jak więc sam widzisz, listdirwersja jest znacznie wydajniejsza. (i to joinjest powolne)

Kałuża
źródło