如何使用os.scandir()以递归方式在目录树上返回DirEntry对象?

Mar*_*ark 16 python python-3.x

Python 3.5的os.scandir(path)函数返回轻量级DirEntry对象,这些对象对文件信息非常有帮助.但是,它只适用于传递给它的直接路径.有没有办法将它包装在递归函数中,以便它访问给定路径下的所有子目录?

Ben*_*oyt 27

您可以使用递归扫描os.walk(),或者如果您需要DirEntry对象或更多控件,请编写如下的递归函数scantree():

try:
    from os import scandir
except ImportError:
    from scandir import scandir  # use scandir PyPI module on Python < 3.5

def scantree(path):
    """Recursively yield DirEntry objects for given directory."""
    for entry in scandir(path):
        if entry.is_dir(follow_symlinks=False):
            yield from scantree(entry.path)  # see below for Python 2.x
        else:
            yield entry

if __name__ == '__main__':
    import sys
    for entry in scantree(sys.argv[1] if len(sys.argv) > 1 else '.'):
        print(entry.path)
Run Code Online (Sandbox Code Playgroud)

笔记:

  • PEP 471os.scandir()文档中还有一些例子.
  • 您还可以在for循环中添加各种逻辑,以跳过'.'以及类似内容开头的目录或文件.
  • 您通常希望follow_symlinks=false在这样的is_dir()递归函数中调用,以避免符号链接循环.
  • 在Python 2.x上,将yield from行替换为:

    for entry in scantree(entry.path):
        yield entry
    
    Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,作为 PEP 471 的一部分,os.walk 已更新为在后台使用 os.scandir。 (3认同)
  • @ShadowRanger 嗯,是的,但是这样它可以使用我的 [scandir](https://pypi.python.org/pypi/scandir) 模块在 Python &lt; 3.5(包括 Python 2.x)上工作。:-) (2认同)
  • os.walk 与 os.scandir —— 我对一个包含超过 400 万个目录和文件的目录运行了这两个函数。os.walk 耗时 34 分 29 秒,os.scandir 耗时 7 分 46 秒。因此,至少对于我的测试来说,os.scandir 的速度大约快 4 1/2 倍。 (2认同)