Python glob模块实战:从基础通配符到递归遍历的完整指南

张开发
2026/4/17 12:08:38 15 分钟阅读

分享文章

Python glob模块实战:从基础通配符到递归遍历的完整指南
1. 为什么需要glob模块在日常开发中文件操作是最常见的需求之一。想象一下这样的场景你需要批量处理某个文件夹下的所有图片文件或者查找项目中所有以_test.py结尾的测试文件。如果手动一个个文件去检查不仅效率低下而且容易出错。这时候就需要glob模块来帮忙了。我第一次接触glob是在处理一个图片分类项目时。当时需要从数千张图片中筛选出所有.jpg格式的风景照片手动操作几乎不可能完成。glob模块用一行代码就解决了这个问题import glob photos glob.glob(images/*.jpg)glob模块是Python标准库中的文件路径查找工具它最大的特点就是支持Unix风格的路径名模式扩展。简单来说就是可以用我们熟悉的通配符比如*、?、[]来匹配文件和目录。这比直接使用os.listdir()后再用正则表达式过滤要方便得多。2. glob模块基础用法2.1 安装与导入glob模块是Python标准库的一部分这意味着你不需要额外安装任何包。只需要在代码开头简单导入即可import glob2.2 基本通配符使用glob模块支持三种基本的通配符*匹配任意数量的字符包括零个字符?匹配单个字符[]匹配指定范围内的字符来看几个实际例子。假设我们有以下目录结构project/ ├── main.py ├── utils.py ├── data/ │ ├── 2023_report.csv │ ├── 2023_summary.xlsx │ └── 2024_plan.docx └── tests/ ├── test_main.py └── test_utils.py要查找所有Python文件py_files glob.glob(project/*.py) # 返回: [project/main.py, project/utils.py]查找data目录下所有2023年的文件data_2023 glob.glob(project/data/2023*) # 返回: [project/data/2023_report.csv, project/data/2023_summary.xlsx]2.3 匹配特定字符集有时候我们需要更精确的匹配。比如只想获取测试文件test_files glob.glob(project/tests/test_?.py) # 返回: [project/tests/test_main.py, project/tests/test_utils.py]或者匹配特定数字开头的文件specific_files glob.glob(project/data/[23]*) # 返回: [project/data/2023_report.csv, project/data/2023_summary.xlsx, project/data/2024_plan.docx]3. 高级文件匹配技巧3.1 递归目录遍历当我们需要处理多层嵌套的目录结构时递归查找就派上用场了。glob模块通过**通配符和recursiveTrue参数实现这一功能。继续使用上面的目录结构假设我们想查找项目中所有的.py文件包括子目录中的all_py_files glob.glob(project/**/*.py, recursiveTrue) # 返回: [project/main.py, project/utils.py, project/tests/test_main.py, project/tests/test_utils.py]这里有几个关键点需要注意**表示匹配任意层级的子目录必须设置recursiveTrue才能启用递归查找路径模式要以**开头或包含**才能递归3.2 处理隐藏文件默认情况下glob不会匹配以点(.)开头的隐藏文件Unix/Linux系统中的隐藏文件。这是有意为之的设计因为这类文件通常是系统或配置文件。如果需要匹配隐藏文件可以显式指定hidden_files glob.glob(.*)3.3 转义特殊字符如果文件名中包含glob的特殊字符如*、?、[等可以使用glob.escape()函数进行转义escaped_path glob.escape(special*file.txt) safe_files glob.glob(escaped_path)4. glob.glob与glob.iglob的深度对比4.1 返回类型差异glob.glob()直接返回匹配路径的列表而glob.iglob()返回一个生成器。这在处理大量文件时有显著区别。# glob.glob返回列表 files_list glob.glob(large_dir/**/*.txt, recursiveTrue) # glob.iglob返回生成器 files_iter glob.iglob(large_dir/**/*.txt, recursiveTrue)4.2 内存使用比较对于包含数千甚至数百万文件的大型目录glob.glob()会一次性将所有匹配路径加载到内存中可能导致内存不足。而glob.iglob()因为是惰性求值只在需要时才生成下一个路径内存占用更小。我曾经处理过一个包含50万图片文件的项目使用glob.glob()直接导致内存溢出换成glob.iglob()后问题解决# 危险可能内存不足 all_images glob.glob(huge_image_lib/**/*.jpg, recursiveTrue) # 安全内存友好 for image_path in glob.iglob(huge_image_lib/**/*.jpg, recursiveTrue): process_image(image_path)4.3 性能实测我做了一个简单的性能测试在一个包含10,000个文件的目录中查找所有.txt文件import time start time.time() list(glob.iglob(test_dir/**/*.txt, recursiveTrue)) print(figlob耗时: {time.time()-start:.4f}秒) start time.time() glob.glob(test_dir/**/*.txt, recursiveTrue) print(fglob耗时: {time.time()-start:.4f}秒)测试结果显示两者在查找时间上差异不大但内存使用差异显著。因此建议文件数量少时用glob.glob()更简单文件数量多或不确定时用glob.iglob()更安全5. 实际应用案例5.1 批量重命名文件假设我们需要将某个目录下所有的.jpg文件改为.png格式import os for jpg_file in glob.iglob(photos/**/*.jpg, recursiveTrue): png_file jpg_file[:-4] .png os.rename(jpg_file, png_file)5.2 项目文件统计统计Python项目中各类文件的数量file_types { Python: len(glob.glob(**/*.py, recursiveTrue)), Markdown: len(glob.glob(**/*.md, recursiveTrue)), Images: len(glob.glob(**/*.{jpg,png,gif}, recursiveTrue)) }5.3 构建自动化测试套件动态发现并运行所有测试文件import unittest def discover_tests(): test_files glob.glob(tests/**/test_*.py, recursiveTrue) for file in test_files: module_name file.replace(/, .).replace(\\, .)[:-3] __import__(module_name) unittest.main()6. 常见问题与解决方案6.1 路径分隔符问题在不同操作系统中路径分隔符可能不同Windows用\Unix用/。为了保证代码跨平台兼容性建议# 不推荐 files glob.glob(folder\subfolder\*.txt) # 推荐 files glob.glob(folder/subfolder/*.txt)glob模块内部会处理路径分隔符的转换。6.2 匹配不到预期文件如果发现glob没有匹配到预期的文件可以检查以下几点当前工作目录是否正确使用os.getcwd()查看路径模式是否正确特别是递归查找时需要**是否设置了recursiveTrue参数文件名是否包含需要转义的特殊字符6.3 性能优化建议当处理超大型文件系统时可以考虑以下优化尽量缩小匹配范围比如指定更具体的目录层级使用更精确的通配符减少匹配数量考虑结合os.scandir()等更低级API对于重复查找可以缓存结果7. 与其他模块的配合使用7.1 结合os模块glob返回的是字符串路径通常需要配合os模块进行进一步操作import os for file in glob.iglob(**/*.tmp, recursiveTrue): if os.path.getsize(file) 0: # 检查文件大小 os.remove(file) # 删除空临时文件7.2 与pathlib整合Python 3.4引入了pathlib模块它提供了更面向对象的路径操作方式from pathlib import Path py_files Path(.).glob(**/*.py) for py_file in py_files: print(fFound Python file: {py_file})pathlib的glob方法与标准库glob模块功能类似但返回的是Path对象而非字符串。7.3 在数据处理中的应用结合pandas等数据分析库批量读取CSV文件import pandas as pd all_data [] for csv_file in glob.iglob(data/**/*.csv, recursiveTrue): df pd.read_csv(csv_file) all_data.append(df) combined pd.concat(all_data)8. 深入理解glob实现原理虽然日常使用不需要了解内部实现但知道glob如何工作有助于更好地使用它。glob模块实际上是基于fnmatch模块实现的后者提供了文件名匹配的功能。当我们调用glob.glob()时大致会发生以下步骤解析输入的路径模式分离目录部分和文件名模式部分如果是递归模式包含**则遍历所有子目录在每个目录中使用fnmatch.fnmatch()匹配文件名收集所有匹配的路径并返回了解这一点后我们就能理解为什么glob在某些情况下可能不如专门的目录遍历工具高效。对于极端性能敏感的场景可能需要考虑使用os.walk()或第三方库如scandir。

更多文章