175

我正在编写一个下降到目录树的脚本(使用 os.walk()),然后访问与某个文件扩展名匹配的每个文件。但是,由于我的工具将用于的某些目录树还包含子目录,而这些子目录又包含很多无用的(出于此脚本的目的)的东西,我想我会添加一个选项供用户指定要从遍历中排除的目录列表。

这很容易使用 os.walk()。毕竟,由我决定是否真的要访问由 os.walk() 产生的相应文件/目录,或者只是跳过它们。问题是,例如,如果我有这样的目录树:

root--
     |
     --- dirA
     |
     --- dirB
     |
     --- uselessStuff --
                       |
                       --- moreJunk
                       |
                       --- yetMoreJunk

而且我想排除uselessStuff及其所有子目录, os.walk() 仍将下降到uselessStuff的所有(可能数千个)子目录中,不用说,这会大大减慢速度。在一个理想的世界里,我可以告诉 os.walk() 甚至不用费心产生更多uselessStuff的孩子的孩子,但据我所知,没有办法这样做(有吗?)。

有人有想法吗?也许有一个第三方库可以提供类似的东西?

4

2 回答 2

295

dirs 就地修改将修剪以下访问的(后续)文件和目录os.walk

# exclude = set(['New folder', 'Windows', 'Desktop'])
for root, dirs, files in os.walk(top, topdown=True):
    dirs[:] = [d for d in dirs if d not in exclude]

从帮助(os.walk):

当 topdown 为真时,调用者可以就地修改 dirnames 列表(例如,通过 del 或 slice 赋值),并且 walk 只会递归到名称保留在 dirnames 中的子目录;这可以用来修剪搜索...

于 2013-11-08T13:10:41.980 回答
9

...@unutbu 出色答案的另一种形式,读起来更直接,因为其目的是排除目录,代价是 O(n**2) 与 O(n) 时间。

list(dirs)(正确执行需要复制 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]
于 2016-05-17T05:16:44.257 回答