このようなホワイトリストのシナリオでは、glob.iglob
を使用してパターンでディレクトリを取得することをお勧めします。これはジェネレーターなので、各結果が見つかるのと同じくらい速く取得できます(注:書面ではos.scandir
ではなくos.listdir
で実装されているので、生成器の半分に過ぎず、各ディレクトリーが熱心にスキャンされ、現在のディレクトリから値を取得すると、次のディレクトリだけをスキャンします)。たとえば、この場合には:
from future_builtins import filter # Only on Py2 to get generator based filter
import os.path
import glob
from operator import methodcaller
try:
from os import scandir # Built-in on 3.5 and above
except ImportError:
from scandir import scandir # PyPI package on 3.4 and below
# If on 3.4+, use glob.escape for safety; before then, if path might contain glob
# special characters and you don't want them processed you need to escape manually
globpat = os.path.join(glob.escape(path), '*', 'TARGET')
# Find paths matching the pattern, filtering out non-directories as we go:
for targetdir in filter(os.path.isdir, glob.iglob(globpat)):
# targetdir is the qualified name of a single directory matching the pattern,
# so if you want to process the files in that directory, you can follow up with:
for fileentry in filter(methodcaller('is_file'), scandir(targetdir)):
# fileentry is a DirEntry with attributes for .name, .path, etc.
は、より高度な使用のためのos.scandir
上のドキュメントを参照してください、またはあなただけであるとして、あなたの元のコードの大部分を維持するために内部ループos.walk
にコールすることができます。
実際にos.walk
を使用する必要がある場合は、dirs
のプルーニングのターゲットを絞ることができます。 TARGET
ディレクトリはすべて1レベル下にする必要があるため、実際はかなり簡単です。 os.walk
がデフォルトでトップダウンします。これは、結果の最初のセットがルートディレクトリ(TARGET
のエントリのみにプルーニングしたくない)になることを意味します。だから、あなたが行うことができます:
import fnmatch
for i, (dirpath, dirs, files) in enumerate(os.walk(path)):
if i == 0:
# Top level dir, prune non-Project dirs
dirs[:] = fnmatch.filter(dirs, 'Project *')
elif os.path.samefile(os.path.dirname(dirpath), path):
# Second level dir, prune non-TARGET dirs
dirs[:] = fnmatch.filter(dirs, 'TARGET')
else:
# Do whatever handling you'd normally do for files and directories
# located under path/Project */TARGET/
'' TARGET 'がdirnamesの場合:dirnames [:] = [' TARGET '] '... – Bakuriu
' glob.glob'を使ってまず 'target'サブディレクトリのリストを取得してから' os .listdir'または 'os.walk'を実行しますか? –
@CABつまり、 'walk'はルートディレクトリを通過しません。 –