【问题标题】:Avoid the base path in a recursive tree walking避免递归树行走中的基本路径
【发布时间】:2020-12-03 21:59:08
【问题描述】:

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

这可以通过:

  • import os, glob
    for f in glob.glob('d:\\temp\\**\\*', recursive=True):
        print(os.path.relpath(f, 'd:\\temp'))
    
  • f.lstrip('d:\\temp\\') 同义,删除此前缀

  • import pathlib
    root = pathlib.Path("d:\\temp")
    print([p.relative_to(root) for p in root.glob("**/*")])
    

这 3 个解决方案有效。但事实上,如果您阅读了glob.py 的来源,它确实会累积/加入所有路径的各个部分。所以上面的解决方案是......“删除之前刚刚添加的东西”!它有效,但不是很优雅。 pathlib 同上,relative_to 删除前缀。

问题:如何修改接下来的几行以在输出中不包含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

【问题讨论】:

  • 风格提示:在路径上使用原始字符串以避免所有转义:r'd:\temp\**\*'。 (顺便说一句,Windows 早在 1995 年就支持路径中的正斜杠,你也可以这样做 r'd:/temp/**/*'

标签: python glob os.path pathlib


【解决方案1】:

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

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)

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

【讨论】:

  • 感谢@facelessuser 这个伟大的解决方案!我刚刚编辑并替换了parent=None,由parent="" 替换,然后os.path.join 始终有效,无需测试父级是否为None。你还好吗?
  • 作为旁注,您的解决方案比我在原始问题中提到的 3 个不满意的解决方案快 2 到 5 倍,太好了! :)(在 1k 个子目录中测试了 20k 个文件)
  • 是的,编译 glob 模式然后进行实际比较会产生更多开销,如果您只想列出文件夹,那么将其全部取出会快得多。 Glob 有它的位置,但如果你不需要匹配文件模式的能力,一个简单的文件列表就足够了。
  • 就更改parent=None 而言,在我的脑海中,我没有看到任何问题,但显然,我还没有在很大程度上对其进行测试。我通常会非常明确地说明我的条件以避免做不必要的工作,但我不认为总是加入会立即出现问题。
猜你喜欢
  • 2012-06-19
  • 1970-01-01
  • 2011-11-27
  • 1970-01-01
  • 1970-01-01
  • 2013-01-14
  • 2021-12-23
  • 1970-01-01
  • 2012-09-13
相关资源
最近更新 更多