HOWTO · Python

Python 计算目录中的文件数

本教程演示了如何在 Python 中计算目录中的文件数。

本页内容

要统计指定目录中的文件条目,可以遍历目录中的条目,并用 Path.is_file() 检查每一项。此检查会跟随符号链接,因此目标为文件的条目也会计入,包括指向文件的符号链接。下面的示例分别说明如何统计目录的直接子项、递归遍历目录树,以及按模式匹配文件。相对路径以 Python 当前工作目录为基准;如果路径位置很重要,请使用绝对路径,或主动设置当前工作目录。

使用 pathlib 统计单个目录中的文件

Path.iterdir() 会生成目录中的直接子项。将它与 Path.is_file() 配合使用,可以统计目标为文件的条目,包括指向文件的符号链接,同时排除子目录。示例会创建一个小型目录树;顶层包含两个文件和一个子目录。

运行此示例:

本节中的代码以及显示的标签或输出仍为英文。

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as temp_dir:
    directory = Path(temp_dir)
    (directory / "alpha.txt").write_text("A", encoding="utf-8")
    (directory / "beta.csv").write_text("B", encoding="utf-8")
    child = directory / "nested"
    child.mkdir()
    (child / "gamma.txt").write_text("C", encoding="utf-8")

    count = sum(1 for entry in directory.iterdir() if entry.is_file())
    print(f"Number of files: {count}")
Number of files: 2

统计结果为两个,因为 iterdir() 只检查直接子项,而 is_file() 会排除 nested 目录。将 directory 改为要检查的路径即可。当任务只涉及一个目录,而且希望使用易读的路径操作时,这是一个很好的默认选择。

使用 os.listdir() 统计单个目录中的文件

os.listdir(directory_path) 会返回指定目录中所有直接子项的名称,其中也包括目录名称。无论 directory_path 是字符串还是其他路径类对象,返回的都是子项名称。先将每个名称与目录路径拼接,再用 os.path.isfile() 检查对应条目的目标是否为文件;这也会统计指向文件的符号链接:

sum(1 for name in os.listdir(directory_path) if os.path.isfile(os.path.join(directory_path, name)))

此计数不会递归。如果省略 directory_path,os.listdir() 会列出当前工作目录。若程序不应依赖启动位置,请传入明确的路径。当后续处理还需要这些名称时,这种方式很实用。

使用 os.scandir() 高效统计文件

os.scandir(directory_path) 会返回一个由 os.DirEntry 对象组成的迭代器。每个条目都可以通过 is_file() 检查类型;默认情况下,此方法会跟随符号链接,因此目标为文件的条目也会计入,包括指向文件的符号链接。计数可以这样写:

sum(1 for entry in os.scandir(directory_path) if entry.is_file())

该迭代器只涵盖直接子项,不包括后代目录中的条目。显式遍历时,使用 with os.scandir(directory_path) as entries: 可以及时关闭目录迭代器。对于大型目录,或需要读取多个条目属性的场景,scandir() 可能是一个实用选择。实际性能取决于文件系统和工作负载;在依据速度差异做决定前,请先测试自己的场景。

使用 os.walk() 递归统计文件

如果要统计目录及其所有后代目录中的文件条目,请使用 os.walk(directory_path)。它会针对遍历到的每个目录,生成当前路径、子目录名称和文件名称。files 列表可能包含目标为文件的符号链接名称,因此将其长度相加也会统计这些条目。对每个 files 列表的长度求和:

sum(len(files) for _, _, files in os.walk(directory_path))

与前面的方法不同,这会统计整个目录树。os.walk() 会在文件列表中报告名称,通常不包括子目录;如果符号链接或目录在遍历期间发生变化会影响结果,请根据应用需求决定如何处理。默认情况下,如果起始目录不存在,函数不会生成任何记录,因此总和为零。

使用 glob.glob() 统计匹配的文件

glob.glob() 会根据模式选择路径。例如,glob.glob(os.path.join(directory_path, "*.txt")) 会匹配指定目录中直接位于该目录下、名称符合 .txt 模式的项。该模式不会递归进入子目录;如果需要匹配嵌套目录中的文件,请将 **/*.txt 这样的递归模式与 recursive=True 一起使用。

模式也可能匹配名称符合条件的目录。要统计目标为文件的条目(包括指向文件的符号链接),请使用 os.path.isfile() 过滤返回的路径:

sum(1 for path in glob.glob(os.path.join(directory_path, "*.txt")) if os.path.isfile(path))

简单统计目录的直接子项时可选择 pathlib;需要子项名称时可选择 listdir();需要条目对象时可选择 scandir();要统计整棵目录树时可选择 os.walk();若要按文件名模式筛选,则可选择 glob.glob()。