使用os.walk定位目录

时间:2016-11-02 16:34:51

标签: python os.walk

由于目录结构庞大且复杂,我的脚本搜索了太多目录:

root--
     |
     --Project A--
                  |
                  -- Irrelevant
                  -- Irrelevant
                  -- TARGET
     |
     --Project B--
                  |
                  -- Irrelevant
                  -- TARGET
                  -- Irrelevant
     |
     -- Irrelevant  --
                       |
                       --- Irrelevant

TARGET目录是我唯一需要遍历的目录,它在每个项目中都有一致的名称(我们在这里只称它为Target)。

我看了这个问题:

Excluding directories in os.walk

但不是排除,我需要包含“目标”目录,该目录不是“根”级别,而是一级向下。

我尝试了类似的东西:

def walker(path):
    for dirpath, dirnames, filenames in os.walk(path):
        dirnames[:] = set(['TARGET'])

但是这个会影响根目录(从而忽略了遍历所需的所有目录,项目A,项目B ......)

2 个答案:

答案 0 :(得分:3)

您的代码的问题在于您总是修改dirnames列表,但这意味着即使在根级别也会删除所有子目录,因此递归调用不会最终访问各种Project X目录。

TARGET存在时,您想要清除其他目录

if 'TARGET' in dirnames:
    dirnames[:] = ['TARGET']

这将允许os.walk调用访问Project X目录,但会阻止它进入Irrelevant目录。

答案 1 :(得分:2)

对于像这样的白名单方案,我建议使用glob.iglob按模式获取目录。它是一个生成器,因此您可以尽快得到每个结果(注意:在撰写本文时,它仍然在os.listdir下实现,而不是{{ 1}},所以它只有一半的生成器;每个目录都是急切地扫描,但只有在它完成后才会扫描下一个目录,从当前目录中产生值)。例如,在这种情况下:

os.scandir

有关更高级用法的信息,请参阅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.walk,那么你可以更有针对性地修剪os.walk。由于您指定所有dirs目录应该只有一个级别,这实际上非常简单。默认情况下,TARGET自上而下,这意味着第一组结果将是根目录(您不想仅修剪os.walk个条目)。所以你可以这样做:

TARGET