2013-08-23 35 views
48

Sto lavorando a uno script per scorrere in modo ricorsivo le sottocartelle in una cartella principale e creare un elenco da un determinato tipo di file. Sto avendo un problema con la sceneggiatura. La sua attualmente impostato come segueRicerca ricorsiva di sottocartelle e restituzione di file in un elenco 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)) 

il problema è che la variabile sottocartella sta tirando in un elenco di sottocartelle, piuttosto che la cartella che il file ITEM si trova. Stavo pensando di eseguire un ciclo for per la sottocartella prima e unirmi alla prima parte del percorso, ma ho pensato a Verifica doppia per vedere se qualcuno ha qualche suggerimento prima. Grazie per l'aiuto!

risposta

83

Si dovrebbe usare il dirpath che si chiama root. Il dirnames viene fornito in modo da poterlo sfoltire se ci sono cartelle che non si desidera inserire in os.walk.

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:

Dopo l'ultima downvote, mi venne in mente che glob è uno strumento migliore per la selezione per estensione.

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

anche una versione generatore

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

Questo sarebbe molto più leggibile se non fosse una lista di comprensione ... –

19

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

glob.glob() ha un nuovo recursive parameter.

Se si vuole ottenere ogni .txt file con my_path (ricorsivamente tra cui sottodirectory):

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' 

Se avete bisogno di un iteratore è possibile utilizzare iglob come alternativa:

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

TypeError: glob() ha un argomento di parole chiave inatteso 'ricorsivo' – CyberJacob

+0

Dovrebbe funzionare. Assicurati di utilizzare una versione> = 3.5. Ho aggiunto un link alla documentazione nella mia risposta per maggiori dettagli. – Rotareti

+0

Ecco perché, sono al numero 2.7 – CyberJacob

2

La sua non è il la risposta più pitone, ma la metterò qui per divertimento perché è una bella lezione di ricorsione

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 

Sulla mia macchina ho due cartelle, root e 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 

Diciamo che voglio trovare tutte .txt e tutti .mid i file in uno di queste directory, quindi posso solo fare

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'] 
Problemi correlati