Исключение каталогов в os.walk
Я пишу script, который спускается в дерево каталогов (используя os.walk()), а затем посещает каждый файл, соответствующий определенному расширению файла. Однако, поскольку некоторые деревья каталогов, в которых мой инструмент будет использоваться, также содержат вспомогательные каталоги, которые, в свою очередь, содержат LOT бесполезные (для целей этого script) вещи, я полагал, d добавьте опцию для указания пользователем списка каталогов для исключения из обхода.
Это достаточно просто с os.walk(). В конце концов, мне решать, действительно ли я хочу посетить соответствующие файлы /dirs, предоставленные os.walk(), или просто пропустить их. Проблема в том, что если у меня есть, например, дерево каталогов:
root--
|
--- dirA
|
--- dirB
|
--- uselessStuff --
|
--- moreJunk
|
--- yetMoreJunk
и я хочу исключить uselessStuff и все его дочерние элементы, os.walk() все равно спустится во все (потенциально тысячи) подкаталогов uselessStuff, что, разумеется, замедляет многое. В идеальном мире я мог бы сказать os.walk(), чтобы даже не потрудиться, уступая больше детям бесполезного Stuff, но, насколько мне известно, нет способа сделать это (есть?).
Есть ли у кого-нибудь идеи? Может быть, есть сторонняя библиотека, которая предоставляет что-то подобное?
Ответы
Ответ 1
Изменение dirs
на месте будет обрезать (последующие) файлы и каталоги, посещенные os.walk
:
# exclude = set([...])
for root, dirs, files in os.walk(top, topdown=True):
dirs[:] = [d for d in dirs if d not in exclude]
Из справки (os.walk):
Когда значение "сверху вниз" истинно, вызывающий может изменить список dirnames на месте (например, через назначение del или slice), и прогулка будет только возвращаться в подкаталоги, имена которых остаются в dirnames; это можно использовать для обрезать поиск...
Ответ 2
... альтернативная форма превосходного ответа @unutbu, который читается чуть более непосредственно, учитывая, что целью является исключение каталогов за счет O (n ** 2) против O (n) времени.
(Для правильного выполнения требуется копирование списка dirs с list(dirs)
)
# exclude = set([...])
for root, dirs, files in os.walk(top, topdown=True):
[dirs.remove(d) for d in list(dirs) if d in exclude]