如何用Python一行代码rglob实现海量文件搜索?

摘要:1. 拒绝“面条代码”:你还在用 os.walk 吗? 你是否遇到过这种场景:你需要在一个拥有几十个子文件夹、成百上千个文件的庞大项目中,找出所有的 .log 日志文件进行分析。 作为一个硬核程序员,你的第一反应可能是祭出 os.walk
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. 概念拆解:地毯式搜索 生活类比:找遥控器 为了理解 glob 和 rglob 的区别,我们来想象一个生活场景:你在家里找电视遥控器。 普通的 glob (Globbing): 这就好比你站在客厅中央,只用眼睛扫视当前房间的桌面和沙发。如果遥控器在卧室或者抽屉里,你是找不到的。glob 只匹配当前目录,不进入子目录。 rglob (Recursive Glob): 这就是 rglob 的威力——递归(Recursive)。这就好比你雇佣了一支专业的搜查队。他们不仅看客厅,还会打开每一扇门(进入子目录),拉开每一个抽屉(进入更深层目录),直到把整个家翻个底朝天,找出所有符合特征的目标。 逻辑图解 想象一棵倒立的树(文件系统): 起点:你指定的根目录。 动作:rglob 会自动沿着树枝向下生长,触达每一个末梢(文件)。 筛选:在遍历的同时,它直接过滤出符合你设定模式(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('*')。
阅读全文