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.

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.


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)

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('/')]

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]

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)

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)])

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)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.