私は、メインフォルダー内のサブフォルダーを再帰的に通過し、特定のファイルタイプからリストを作成するスクリプトに取り組んでいます。スクリプトに問題があります。現在、次のように設定されています
for root, subFolder, files in os.walk(PATH):
for item in files:
if item.endswith(".txt") :
fileNamePath = str(os.path.join(root,subFolder,item))
問題は、subFolder変数がITEMファイルのあるフォルダーではなくサブフォルダーのリストを取得することです。私は以前にサブフォルダーに対してforループを実行してパスの最初の部分に参加することを考えていましたが、その前に誰かに提案があるかどうかを確認するためにIdをダブルチェックしました。ご協力いただきありがとうございます!
dirpath
と呼ぶroot
を使用する必要があります。 dirnames
が提供されているので、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']
編集:
最新のダウン投票の後、glob
が拡張子による選択に適したツールであることがわかりました。
import os
from glob import glob
result = [y for x in os.walk(PATH) for y in glob(os.path.join(x[0], '*.txt'))]
ジェネレーターバージョンも
from itertools import chain
result = (chain.from_iterable(glob(os.path.join(x[0], '*.txt')) for x in os.walk('.')))
Edit [2 for Python 3.4 +
from pathlib import Path
result = list(Path(".").rglob("*.[tT][xX][tT]"))
変更されたPython 3.5:「**」を使用した再帰的グロブのサポート。
glob.glob()
に新しい 再帰パラメーター が追加されました。
.txt
の下にあるすべてのmy_path
ファイル(再帰的にサブディレクトリを含む)を取得する場合:
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'
イテレータが必要な場合は、代わりに iglob を使用できます。
for file in glob.iglob(my_path, recursive=False):
# ...
John La Rooyのリスト内包表記 をネストされたforに変換します。
result = [y for x in os.walk(PATH) for y in glob(os.path.join(x[0], '*.txt'))]
以下と同等である必要があります:
import glob
result = []
for x in os.walk(PATH):
for y in glob.glob(os.path.join(x[0], '*.txt')):
result.append(y)
これは最もPython的な答えではありませんが、再帰のきちんとしたレッスンなので、ここで楽しみにしています。
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
私のマシンには、root
とroot2
の2つのフォルダーがあります
mender@multivax ]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
これらのディレクトリのいずれかですべての.txt
およびすべての.mid
ファイルを検索したいとしましょう。
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']
新しいpathlib
ライブラリは、これを1行に単純化します。
from pathlib import Path
result = list(Path(PATH).glob('**/*.txt'))
ジェネレーターバージョンも使用できます。
from pathlib import Path
for file in Path(PATH).glob('**/*.txt'):
pass
これはPath
オブジェクトを返します。これはほとんど何でも使用できます。また、file.name
によってファイル名を文字列として取得できます。
再帰はPython 3.5で新しく追加されたため、Python 2.7では動作しません。以下はr
文字列を使用する例です。Win、Lin、...のいずれかでパスをそのまま提供する必要があります。
import glob
mypath=r"C:\Users\dj\Desktop\nba"
files = glob.glob(mypath + r'\**\*.py', recursive=True)
# print(files) # as list
for f in files:
print(f) # Nice looking single line per file
注:いくら深くても、すべてのファイルがリストされます。