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)