Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 避免递归树遍历中的基本路径_Python_Glob_Os.path_Pathlib - Fatal编程技术网

Python 避免递归树遍历中的基本路径

Python 避免递归树遍历中的基本路径,python,glob,os.path,pathlib,Python,Glob,Os.path,Pathlib,我知道如何使用各种方法递归列出d:\temp的所有文件/文件夹,请参阅。 但我通常希望避免在结果中使用d:\temp\前缀,而是使用到该基的相对路径 这可以通过以下方式实现: 用f.lstrip('d:\\temp\\')删除此前缀 这三种解决方案都有效。但事实上,如果您阅读glob.py的源代码,它确实会累积/连接路径的所有部分。所以上面的解决方案是。。。“删除之前刚刚添加的内容”!它能用,但不是很优雅。用relative_to删除前缀的pathlib的Idem 问题:如何修改接

我知道如何使用各种方法递归列出
d:\temp
的所有文件/文件夹,请参阅。
但我通常希望避免在结果中使用
d:\temp\
前缀,而是使用到该基的相对路径

这可以通过以下方式实现:

  • f.lstrip('d:\\temp\\')
    删除此前缀

这三种解决方案都有效。但事实上,如果您阅读
glob.py
的源代码,它确实会累积/连接路径的所有部分。所以上面的解决方案是。。。“删除之前刚刚添加的内容”!它能用,但不是很优雅。用
relative_to
删除前缀的
pathlib
的Idem

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

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

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中,将有一个新选项,允许您使用内置的glob毫无问题地执行此操作:

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

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

感谢@facelessuser提供了这个伟大的解决方案!我刚刚编辑并将
parent=None
替换为
parent=”“
,然后
os.path.join
始终有效,无需测试parent是否为None。这对您合适吗?作为旁注,您的解决方案比我在原始问题中提到的3个不满意的解决方案快2到5倍,太好了!:)(使用1k子目录中的20k文件进行测试)是的,编译glob模式然后进行实际比较会有更多的开销,如果您只想列出文件夹,那么将其全部删除会快得多。Glob有它的位置,但是如果你不需要匹配文件模式的能力,一个简单的文件列表就足够了。就更改
parent=None
而言,从我的头脑中,我看不出有什么问题,但很明显,我还没有对它进行很大程度的测试。为了避免做不必要的工作,我通常会非常明确地说明我的条件,但我认为总是加入并没有立即的问题。风格提示:在路径上使用rawstrings以避免所有转义:
r'd:\temp\***'
。(顺便说一句,Windows从1995年起就支持路径中的正斜杠,您也可以执行
r'd:/temp/***'
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)
import glob
glob.glob('**/*', root_dir='d:\\temp', recursive=True)