首页 > 解决方案 > 避免递归树行走中的基本路径

问题描述

我知道如何d:\temp使用各种方法递归列出所有文件/文件夹,请参阅如何使用 glob() 递归查找文件?.
但通常我想避免d:\temp\在结果中使用前缀,而是使用到此基础的相对路径。

这可以通过以下方式完成:

这 3 个解决方案有效。但实际上,如果您阅读 的源代码glob.py,它确实会累积/连接路径的所有部分。所以上面的解决方案是......“删除之前刚刚添加的东西”!它有效,但不是很优雅。Idem for pathlibwith relative_towhich 删除前缀。

问题:如何修改接下来的几行以不包含d:\temp在输出中(不删除之前连接的内容!)?

import os

def listpath(path):
    for f in os.scandir(path):
        f2 = os.path.join(path, f)
        if os.path.isdir(f):
            yield f2
            yield from listpath(f2)
        else:
            yield f2

for f in listpath('d:\\temp'):
    print(f)

#d:\temp\New folder
#d:\temp\New folder\New Text Document - Copy.txt
#d:\temp\New folder\New Text Document.txt
#d:\temp\New Text Document - Copy.txt
#d:\temp\New Text Document.txt

标签: pythonglobos.pathpathlib

解决方案


您可以执行以下示例中所示的操作。基本上,我们递归地返回将它们连接在一起的路径部分,但我们不加入初始根。

import os

def listpath(root, parent=''):
    scan = os.path.join(root, parent)
    for f in os.scandir(scan):
        f2 = os.path.join(parent, f.name)
        yield f2
        if f.is_dir():
            yield from listpath(root, f2)

for f in listpath('d:\\temp'):
    print(f)

在尚未发布的 Python 3.10 中,将有一个新root_dir选项允许您毫无问题地使用内置 glob 执行此操作:

import glob
glob.glob('**/*', root_dir='d:\\temp', recursive=True)

您还可以使用 3rd 方库,例如已经实现此行为的wcmatch库(我是该库的作者)。但在这种简单的情况下,您的listpath方法可能就足够了。


推荐阅读