web-dev-qa-db-ja.com

再帰的なサブフォルダーの検索とリスト内のファイルの戻り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))

問題は、subFolder変数がITEMファイルのあるフォルダーではなくサブフォルダーのリストを取得することです。私は以前にサブフォルダーに対してforループを実行してパスの最初の部分に参加することを考えていましたが、その前に誰かに提案があるかどうかを確認するためにIdをダブルチェックしました。ご協力いただきありがとうございます!

83
user2709514

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]"))
129
John La Rooy

変更された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):
    # ...
70
Rotareti

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)

リスト内包表記 および関数 os.walk および glob.glob のドキュメントがあります。

14
Jefferson Lima

これは最も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

私のマシンには、rootroot2の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']
5
dermen

新しい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によってファイル名を文字列として取得できます。

5
Emre

再帰は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

注:いくら深くても、すべてのファイルがリストされます。

0
prosti