如何在Python中获取所有直接子目录

215 投票
17 回答
240266 浏览
提问于 2025-04-15 11:18

我正在尝试写一个简单的Python脚本,这个脚本会把一个叫做index.tpl的文件复制到所有子目录下,命名为index.html(不过有几个例外)。

我现在遇到麻烦了,因为我在获取子目录的列表时卡住了。

17 个回答

79

为什么没有人提到 glob 呢? glob 这个工具可以让你用类似Unix系统的路径方式来查找文件,它几乎是我用来寻找多个路径名的首选方法。使用起来非常简单:

from glob import glob
paths = glob('*/')

需要注意的是,glob 会返回带有最后一个斜杠的目录(就像Unix系统那样),而大多数基于 path 的解决方案则不会加上最后的斜杠。

255
import os
def get_immediate_subdirectories(a_dir):
    return [name for name in os.listdir(a_dir)
            if os.path.isdir(os.path.join(a_dir, name))]

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。

162

我对几种函数进行了速度测试,目的是获取所有当前子目录的完整路径

简单来说: 总是使用 scandir

list_subfolders_with_paths = [f.path for f in os.scandir(path) if f.is_dir()]

额外提示:使用 scandir 你还可以只获取文件夹名称,只需用 f.name 替代 f.path

需要注意的是,这个方法(以及下面提到的所有其他方法)不会使用自然排序。这意味着结果的排序方式是这样的:1, 10, 2。如果你想要自然排序(1, 2, 10),可以查看这个链接:https://stackoverflow.com/a/48030307/2441026




测试结果scandir 的速度是 walk 的3倍,是 listdir(带过滤)的32倍,是 Pathlib 的35倍,是 listdir 的36倍,甚至是 glob 的37倍!

Scandir:           0.977
Walk:              3.011
Listdir (filter): 31.288
Pathlib:          34.075
Listdir:          35.501
Glob:             36.277

测试是在 W7x64 系统上进行的,使用 Python 3.8.1,文件夹里有440个子文件夹。
如果你在想 listdir 是否可以通过不重复使用 os.path.join() 来加速,答案是可以,但差别几乎可以忽略不计。

代码:

import os
import pathlib
import timeit
import glob

path = r"<example_path>"



def a():
    list_subfolders_with_paths = [f.path for f in os.scandir(path) if f.is_dir()]
    # print(len(list_subfolders_with_paths))


def b():
    list_subfolders_with_paths = [os.path.join(path, f) for f in os.listdir(path) if os.path.isdir(os.path.join(path, f))]
    # print(len(list_subfolders_with_paths))


def c():
    list_subfolders_with_paths = []
    for root, dirs, files in os.walk(path):
        for dir in dirs:
            list_subfolders_with_paths.append( os.path.join(root, dir) )
        break
    # print(len(list_subfolders_with_paths))


def d():
    list_subfolders_with_paths = glob.glob(path + '/*/')
    # print(len(list_subfolders_with_paths))


def e():
    list_subfolders_with_paths = list(filter(os.path.isdir, [os.path.join(path, f) for f in os.listdir(path)]))
    # print(len(list(list_subfolders_with_paths)))


def f():
    p = pathlib.Path(path)
    list_subfolders_with_paths = [x for x in p.iterdir() if x.is_dir()]
    # print(len(list_subfolders_with_paths))



print(f"Scandir:          {timeit.timeit(a, number=1000):.3f}")
print(f"Listdir:          {timeit.timeit(b, number=1000):.3f}")
print(f"Walk:             {timeit.timeit(c, number=1000):.3f}")
print(f"Glob:             {timeit.timeit(d, number=1000):.3f}")
print(f"Listdir (filter): {timeit.timeit(e, number=1000):.3f}")
print(f"Pathlib:          {timeit.timeit(f, number=1000):.3f}")

撰写回答