使用 glob 递归获取终端子目录

Using glob to recursively get terminal subdirectories

提问人:Clay 提问时间:11/15/2023 更新时间:11/15/2023 访问量:36

问:

我有一系列子目录,其中包含文件:

/cars/ford/escape/sedan/
/cars/ford/escape/coupe/
/cars/ford/edge/sedan/
/cars/ferrari/testarossa/
/cars/kia/soul/coupe/

诸如此类。

我想使用 glob(在 Python 中)从根目录获取所有这些终端子目录路径,但不包括其中的任何文件,也不包含子目录的任何父目录。每个目录都只包含文件,没有其他子目录。/cars/

我尝试使用 ,但它也返回 、 、 等。我不想要这些。glob("**/")/cars/ford//cars/ford/escape//cars/ford/edge/cars/ferrari/

我也尝试使用,但这也会返回终端子目录中的所有文件。rglob("*/")

我可以通过整理文件并从他们的父母那里得到我需要的东西,但我觉得从整体方面必须有一个优雅的解决方案。不幸的是,我似乎找不到合适的搜索词来发现它。谢谢!

python glob

评论

1赞 Charles Duffy 11/15/2023
这不是标准通配本身所支持的东西。您要么需要后处理,要么使用其他工具。
1赞 Charles Duffy 11/15/2023
顺便说一句,关于“使用<工具>”限制的说明:如 stackoverflow.com/help/dont-ask 所示,Stack Overflow 专注于实际的、可回答的问题;学术或只是为了练习而练习是不受欢迎的。如果你有一个实际的理由,你不能使用glob以外的东西,一定要进入这个限制背后的原因,我们可以尝试弄清楚如何在实践中解决它;但一般来说,为了绕过一个完全人为的限制而弯腰,是我们的规则中可以推翻的东西。
0赞 Clay 11/15/2023
glob 本身没有限制,我只是不知道其他工具,并希望以更优雅的方式完成过滤,而不是收集所有文件名并随后进行逻辑过滤掉所需的路径。我想一定有一种方法可以在我的球形模式中做到这一点。

答:

3赞 Charles Duffy 11/15/2023 #1

glob是这项工作的错误工具:传统的 POSIX-y glob 表达式不支持任何类型的否定断言(extglob 支持,但它仍然是一种限制性支持——对单个名称进行断言,而不是对同一文件系统上存在或不存在的内容进行断言——这不适用于您的用例,并且 Python 无论如何都不支持它们)。 而它的新孩子更适合。os.walk()

假设您使用的是足够新的 Python 来支持 pathlib。路径 .walk():

import pathlib

def terminal_dirs(parent):
    for root, dirs, files in pathlib.Path(parent).walk():
        if not dirs:
            yield root

对于旧版本的 Python,可以类似地使用:os.walk()

import os

def terminal_dirs(parent):
    for dirpath, dirnames, filenames in os.walk(parent):
        if not dirnames:
            yield dirpath

当然,如果匆忙,这两者都可以折叠成单行:

result = [ r for (r,d,f) in os.walk('/cars') if not d ]