Python用fnmatch过滤列表中的通配符文件名

周叙
周叙
发布时间:2026-10-27| 6人浏览过
原创

详细讲解如何在Python中使用标准库fnmatch模块对内存中的文件名列表进行通配符模式过滤,包括fnmatch.filter的使用、通配符语法、跨平台大小写处理及与glob的区别。

当我们在 Python 中处理文件名时,经常会拿到一个包含大量文件名的纯字符串列表(例如解压包目录清单、网络接口返回的文件名列表或 os.listdir() 的输出),并希望像在命令行中那样使用 *.py 或 data_??.csv 这样的通配符快速选出目标项。Python 内置的 fnmatch 模块正是完成这项任务的核心工具,其中的 fnmatch.filter() 能够直接对内存列表执行通配符过滤,省去手动编写正则或遍历磁盘的繁琐开销。

一、核心解决方案:使用 fnmatch.filter()

如果已经有一个文件名列表,最直接且高效的方法是调用 fnmatch.filter(names, pattern)。它接收一个字符串可迭代对象和一个包含通配符的模式串,返回匹配该模式的新列表。

import fnmatch

file_names = [
    "app.py",
    "test_app.py",
    "config.yaml",
    "database.sql",
    "log_2026_01.txt",
    "log_2026_02.txt",
    "report.pdf"
]

# 过滤出所有以 .py 结尾的文件
python_files = fnmatch.filter(file_names, "*.py")
print("Python脚本列表:", python_files)

# 过滤出特定前缀的日志文件
monthly_logs = fnmatch.filter(file_names, "log_2026_??.txt")
print("2026年日志列表:", monthly_logs)

示例输出:

Python脚本列表: ['app.py', 'test_app.py']
2026年日志列表: ['log_2026_01.txt', 'log_2026_02.txt']

与使用列表推导式配合单个匹配函数相比,fnmatch.filter() 内部做了针对性优化,在处理大规模列表时速度更快、意图更清晰。

Python用fnmatch过滤列表中的通配符文件名
图 1:fnmatch.filter() 对内存中文件名列表的过滤流程与内部机制

二、fnmatch 支持的通配符语法

fnmatch 遵循 Unix Shell 风格的通配符规则(Glob 语法),不同于完整的正则表达式,其语法非常精炼:

模式符号 含义解释 示例 匹配项举例
* 匹配任意长度的字符序列(包括空字符) *.csv data.csv, .csv, user_info.csv
? 匹配任意单个字符 file_?.txt file_1.txt, file_a.txt(不匹配 file_10.txt)
[seq] 匹配方括号序列内的任意单个字符 image_[0-9].png image_3.png, image_7.png
[!seq] 匹配不在方括号序列内的任意单个字符 temp_[!a-z].dat temp_1.dat, temp_#.dat(不匹配 temp_c.dat)
语法注意点:反向匹配使用的是感叹号 [!seq],而不是正则表达式中常见的脱字符 [^seq]。虽然部分扩展环境也能容忍 ^,但为了保证跨环境兼容性,务必遵循标准写为 [!...]。

三、函数矩阵:选择适合业务场景的接口

fnmatch 模块提供了四个主要函数。理解它们的定位有助于避免代码冗余和隐蔽的跨平台缺陷:

import fnmatch

filename = "MainController.PY"

# 1. 批量过滤列表:fnmatch.filter(names, pattern)
filtered = fnmatch.filter(["a.py", "b.txt"], "*.py")

# 2. 单项判定(大小写敏感度取决于操作系统):fnmatch.fnmatch(name, pattern)
is_py = fnmatch.fnmatch(filename, "*.py")

# 3. 严格区分大小写的单项判定:fnmatch.fnmatchcase(name, pattern)
is_py_case = fnmatch.fnmatchcase(filename, "*.py")  # 恒为 False

# 4. 查看转换后的底层正则表达式:fnmatch.translate(pattern)
regex_str = fnmatch.translate("*.py")
print("转换后的正则表达式:", regex_str)
Python用fnmatch过滤列表中的通配符文件名
图 2:fnmatch 模块四项关键能力在参数、大小写策略及场景上的全景对比

四、容易混淆的常见说法与深度辨析

说法辨析 1:“过滤文件名一定要用 glob 模块”

这种说法在初学者中十分常见,但它混淆了“文件系统遍历”与“纯内存字符串匹配”的职责边界。

  • 何时成立:当你的目标是从物理硬盘的某个文件夹中扫描出存在的文件时,使用 glob.glob() 或 pathlib.Path.glob() 确实一步到位。
  • 为何需要修正:很多场景下文件名列表早已存在于内存中。例如:从压缩包中读取 zip_file.namelist()、从 FTP/S3 接口拉取对象键列表、或对已有的过滤中间结果进行二次提炼。此时如果为了用 glob 而把列表写入磁盘或尝试拼接假路径,不仅执行效率低下,而且会带来不必要的 I/O 开销与错误风险。fnmatch 专注于对纯字符串列表进行模式匹配,是纯粹的无状态运算。

说法辨析 2:“fnmatch 的匹配结果在不同操作系统上完全一致”

这是导致线上环境出现诡异 Bug 的典型原因之一。

  • 看似合理的原因:Python 标准库多数模块具有优良的跨平台抽象,读者往往默认字符串匹配行为也是跨平台中立的。
  • 实际机制与修正:fnmatch.fnmatch() 和 fnmatch.filter() 内部会调用 os.path.normcase()。在 Windows 和 macOS(部分文件系统)上,文件名是不区分大小写的,因此 *.PY 能够成功匹配 app.py;但在 Linux 服务器上,文件系统严格区分大小写,*.PY 将无法匹配 app.py。
  • 防坑做法:如果项目需要在 Linux 服务器与 Windows 本地开发机之间保持一致的严格匹配,应显式采用 fnmatch.fnmatchcase(),例如:
    [f for f in file_names if fnmatch.fnmatchcase(f, "*.py")]
Python用fnmatch过滤列表中的通配符文件名
图 3:fnmatch、glob 与 re 模块的分工界限与选型决策维度

五、实战技巧:多模式组合与复杂过滤

在实际业务中,过滤需求往往不是单个后缀那么单一,例如需要“同时匹配所有的 png 和 jpg 文件”,或者“排除所有备份文件”。以下是处理这类需求的实用做法:

1. 匹配多种文件扩展名

fnmatch 原生不支持 *.(png|jpg) 这种正则中的管道分支。要实现多条件筛选,最清晰的做法是循环匹配并利用集合去重:

import fnmatch

all_files = [
    "banner.PNG", "avatar.jpg", "script.py", 
    "vector.svg", "photo.jpeg", "data.json"
]

patterns = ["*.jpg", "*.jpeg", "*.png"]
matched_files = []

for pat in patterns:
    # 结合大小写归一化
    matched_files.extend(fnmatch.filter(all_files, pat))

# 保持顺序并去重
unique_matches = list(dict.fromkeys(matched_files))
print("图片资源列表:", unique_matches)

2. 包含与排除组合过滤

先通过白名单模式筛选候选集,再通过黑名单模式剔除临时或测试文件:

import fnmatch

source_files = [
    "service.py", "test_service.py", "utils.py",
    "test_utils.py", "models.py", "temp_models.py"
]

# 第一步:提取全部 Python 文件
candidates = fnmatch.filter(source_files, "*.py")

# 第二步:排除 test_ 开头与 temp_ 开头的文件
excluded = set(fnmatch.filter(candidates, "test_*")) | set(fnmatch.filter(candidates, "temp_*"))
production_files = [f for f in candidates if f not in excluded]

print("正式生产代码:", production_files)
# 输出: ['service.py', 'utils.py', 'models.py']

六、知识总结与避坑检查清单

为了方便在日后开发中快速参考与排查,这里将使用 fnmatch 过滤文件名时的核心准则提炼为如下自查卡片:

Python用fnmatch过滤列表中的通配符文件名
图 4:fnmatch 过滤文件名四项核心开发自查清单
相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。