别再手写递归找文件了!用 Python rglob 一行代码搞定海量搜索

1. 拒绝“面条代码”:你还在用 os.walk 吗?

你是否遇到过这种场景:你需要在一个拥有几十个子文件夹、成百上千个文件的庞大项目中,找出所有的 .log 日志文件进行分析。

作为一个硬核程序员,你的第一反应可能是祭出 os.walk 并在里面嵌套两层 for 循环,或者更惨——自己写一个递归函数(Recursion)去遍历文件夹。

写完之后,代码可能是这样的:

Python
import os

# 传统的痛苦写法
target_files = []
for root, dirs, files in os.walk('my_project'):
    for file in files:
        if file.endswith('.log'):
            target_files.append(os.path.join(root, file))

这段代码能跑,但它并不优雅。它把“遍历逻辑”和“筛选逻辑”混在了一起,不仅难读,而且容易写错。

今天我要介绍的 rglob,就是为了终结这种痛苦而生的。 它是 Python 3.4 引入的 pathlib 模块中的核武器,能让你用一行代码,优雅地完成上述所有工作。


2. 概念拆解:地毯式搜索

生活类比:找遥控器

为了理解 globrglob 的区别,我们来想象一个生活场景:你在家里找电视遥控器。

  • 普通的 glob (Globbing): 这就好比你站在客厅中央,只用眼睛扫视当前房间的桌面和沙发。如果遥控器在卧室或者抽屉里,你是找不到的。glob 只匹配当前目录,不进入子目录。

  • rglob (Recursive Glob): 这就是 rglob 的威力——递归(Recursive)。这就好比你雇佣了一支专业的搜查队。他们不仅看客厅,还会打开每一扇门(进入子目录),拉开每一个抽屉(进入更深层目录),直到把整个家翻个底朝天,找出所有符合特征的目标。

逻辑图解

想象一棵倒立的树(文件系统):

  1. 起点:你指定的根目录。

  2. 动作rglob 会自动沿着树枝向下生长,触达每一个末梢(文件)。

  3. 筛选:在遍历的同时,它直接过滤出符合你设定模式(Pattern)的文件。


3. 动手实战:三行代码的魔法

让我们抛弃 os 模块,拥抱现代化的 pathlib

Hello World:找出所有 Python 文件

假设你的项目结构很深,你想列出所有的 .py 文件。

Python
from pathlib import Path

# 1. 定义起点(当前目录)
current_dir = Path('.') 

# 2. 发动 rglob 引擎
# 这里的 '*.py' 就是我们要找的特征
python_files = current_dir.rglob('*.py')

# 3. 打印结果
for file_path in python_files:
    print(file_path)

代码解析:

  • Path('.'):这是面向对象的文件路径写法,比字符串路径更智能。

  • .rglob('*.py'):核心所在。r 代表 Recursive(递归)。它告诉 Python:“去在这个目录及其所有子目录中,找到后缀是 .py 的家伙。”

  • 返回值:注意,这里返回的不是一个死列表,而是一个生成器(Generator)。这意味着即使有 100 万个文件,它也不会瞬间撑爆你的内存,而是你通过 for 循环要一个,它给一个。

同样的功能,对比一下 os 模块?

  • os 模块写法:需要 5-6 行,逻辑嵌套。

  • rglob 写法:1 行核心代码,逻辑扁平,语义清晰。


4. 进阶深潜:你必须知道的细节

虽然 rglob 很强,但在生产环境中使用时,有几个关键点需要注意。

A. 通配符的艺术

rglob 支持标准的 Unix shell 风格通配符:

  • rglob('*.jpg'):所有 JPG 图片。

  • rglob('test_*.py'):所有以 test_ 开头的 Python 测试文件。

  • rglob('**/config.yaml'):这也行?是的!其实 rglob('*') 等同于 glob('**/*')。在 pathlib 中,** 本身就代表递归目录。

B. 性能陷阱:不要搜全盘!

千万不要在根目录(如 /C:\)下运行 Path('/').rglob('*')。 因为 rglob 会尝试遍历整个文件系统。如果你的目录包含 node_modules (前端噩梦) 或 .git 文件夹,文件数量可能高达数十万。

最佳实践: 尽量缩小搜索范围,或者在遍历时手动排除特定目录(虽然 rglob 本身不带排除参数,你可能需要在循环中加个 if 判断)。

C. 想要列表怎么办?

前面提到 rglob 返回的是生成器。如果你确定文件数量不多,想直接要一个列表:

Python
# 强制转换为列表
all_images = list(Path('./images').rglob('*.png'))
print(f"一共找到了 {len(all_images)} 张图片")

5. 总结与延伸

核心知识点

  1. pathlib 是未来:尽量用 pathlib.Path 替代 os.path

  2. rglob 是递归神器:它能自动穿透多层文件夹查找文件,无需手写循环。

  3. 生成器机制:它是惰性求值的,省内存,适合处理大量文件。

posted @ 2026-01-06 09:17  Swizard  阅读(46)  评论(0)    收藏  举报