2013-08-23 22 views
48

Pracuję nad skryptem rekursywnie przechodzącym przez podfoldery w folderze głównym i budującym listę określonego typu plików. Mam problem ze skryptem. Jest aktualnie ustawiony następującoRekurencyjne wyszukiwanie podfolderów i zwracanie plików na liście python

for root, subFolder, files in os.walk(PATH): 
    for item in files: 
     if item.endswith(".txt") : 
      fileNamePath = str(os.path.join(root,subFolder,item)) 

problemem jest to, że zmienna podfolder ciągnie się na liście podfolderów zamiast folderu plik POZYCJA znajduje. Myślałem o uruchomieniu pętli for dla podfolderu i dołączeniu do pierwszej części ścieżki, ale pomyślałem, że sprawdzę, czy ktoś ma jakieś sugestie przed tym. Dzięki za pomoc!

Odpowiedz

83

Powinieneś używać dirpath, którą nazywasz root. Dostarczone są dirnames, dzięki czemu można je przycinać, jeśli istnieją foldery, których nie chcesz, aby się powtarzały.

import os 
result = [os.path.join(dp, f) for dp, dn, filenames in os.walk(PATH) for f in filenames if os.path.splitext(f)[1] == '.txt'] 

Edit:

Po ostatniej downvote, dotarło do mnie, że glob jest lepszym narzędziem do wybierania przez rozszerzenie.

import os 
from glob import glob 
result = [y for x in os.walk(PATH) for y in glob(os.path.join(x[0], '*.txt'))] 

również wersja generatora

from itertools import chain 
result = (chain.from_iterable(glob(os.path.join(x[0], '*.txt')) for x in os.walk('.'))) 
+0

Byłoby to o wiele bardziej czytelne, gdyby nie było to zrozumienie listy ... –

19

Changed in Python 3.5: Support for recursive globs using “**”.

glob.glob() dostał nową recursive parameter.

Jeśli chcesz uzyskać każdy plik .txt pod my_path (rekursywnie włącznie z podkatalogami)

import glob 

files = glob.glob(my_path + '/**/*.txt', recursive=True) 

# my_path/  the dir 
# **/  every file and dir under my_path 
# *.txt  every file that ends with '.txt' 

Jeśli potrzebujesz iterator można użyć iglob jako alternatywę:

for file in glob.iglob(my_path, recursive=False): 
    # ... 
+1

TypeError: glob() dostał nieoczekiwany argument słowa kluczowego "rekurencyjny" – CyberJacob

+0

Powinien działać. Upewnij się, że używasz wersji> = 3.5. Dodałem link do dokumentacji w mojej odpowiedzi, aby uzyskać więcej szczegółów. – Rotareti

+0

To jest powód, dla którego jestem na 2.7 – CyberJacob

2

jej nie najbardziej pythonic odpowiedź, ale będę tu dla zabawy, ponieważ jest to lekcja schludny w rekurencji

def find_files(files, dirs=[], extensions=[]): 
    new_dirs = [] 
    for d in dirs: 
     try: 
      new_dirs += [ os.path.join(d, f) for f in os.listdir(d) ] 
     except OSError: 
      if os.path.splitext(d)[1] in extensions: 
       files.append(d) 

    if new_dirs: 
     find_files(files, new_dirs, extensions) 
    else: 
     return 

Na moim komputerze mam dwa foldery, root i root2

[email protected] ]ls -R root root2 
root: 
temp1 temp2 

root/temp1: 
temp1.1 temp1.2 

root/temp1/temp1.1: 
f1.mid 

root/temp1/temp1.2: 
f.mi f.mid 

root/temp2: 
tmp.mid 

root2: 
dummie.txt temp3 

root2/temp3: 
song.mid 

Powiedzmy chcę znaleźć wszystkie .txt i wszystkie .mid plików w każdym z tych katalogów, to mogę po prostu zrobić

files = [] 
find_files(files, dirs=['root','root2'], extensions=['.mid','.txt']) 
print(files) 

#['root2/dummie.txt', 
# 'root/temp2/tmp.mid', 
# 'root2/temp3/song.mid', 
# 'root/temp1/temp1.1/f1.mid', 
# 'root/temp1/temp1.2/f.mid'] 
Powiązane problemy