Для сценария с подобным списком я бы предложил использовать glob.iglob
, чтобы получить каталоги по шаблону. Это генератор, поэтому вы получите каждый результат так быстро, как он их найдет (Примечание: на момент написания он по-прежнему реализован с os.listdir
под капотом, а не os.scandir
, так что это всего лишь половина генератора, каждый каталог сканируется с нетерпением, но он проверяет только следующую директорию после завершения ввода значений из текущего каталога). Например, в данном случае:
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
должны быть только на один уровень вниз, это на самом деле довольно легко. 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/
Попробуйте: 'if 'TARGET' в dirnames: dirnames [:] = ['TARGET']' ... – Bakuriu
как с помощью 'glob.glob' сначала получить список подцелей« target », а затем использовать' os .listdir' или 'os.walk' по результатам? –
@CAB Это означает, что 'walk' не пройдет мимо корневого каталога. –