7.5. fnmatch — Unix 风格的 Glob 文件名规则匹配

目的:处理 Unix 风格的文件名比较

fnmatch 用于比较针对 Unix shell 所使用的 glob-style 模式的文件名。

简单匹配

fnmatch() 将一个模式与一个文件名进行比较,返回一个 bool 值表示它们是否匹配。比较是否大小写敏感依赖于操作系统是否使用了大小写敏感的文件系统。

fnmatch_fnmatch.py

import fnmatch
import os

pattern = 'fnmatch_*.py'
print('Pattern :', pattern)
print()

files = os.listdir('.')
for name in sorted(files):
    print('Filename: {:<25} {}'.format(
        name, fnmatch.fnmatch(name, pattern)))

这个例子中,模式将匹配所有以 fnmatch_ 开始并以 .py 结尾的文件。

$ python3 fnmatch_fnmatch.py

Pattern : fnmatch_*.py

Filename: fnmatch_filter.py         True
Filename: fnmatch_fnmatch.py        True
Filename: fnmatch_fnmatchcase.py    True
Filename: fnmatch_translate.py      True
Filename: index.rst                 False

为了强制进行大小写敏感方式比较,忽略操作系统系统设置,应该使用 fnmatchcase()

fnmatch_fnmatchcase.py

import fnmatch
import os

pattern = 'FNMATCH_*.PY'
print('Pattern :', pattern)
print()

files = os.listdir('.')

for name in sorted(files):
    print('Filename: {:<25} {}'.format(
        name, fnmatch.fnmatchcase(name, pattern)))

用于测试程序的 OS X 系统使用了大小写敏感方式文件系统,所以修改后的模式没有匹配到任何文件。

$ python3 fnmatch_fnmatchcase.py

Pattern : FNMATCH_*.PY

Filename: fnmatch_filter.py         False
Filename: fnmatch_fnmatch.py        False
Filename: fnmatch_fnmatchcase.py    False
Filename: fnmatch_translate.py      False
Filename: index.rst                 False

过滤

为了检测一个文件名序列,请使用 filter(),它将返回一个匹配模式参数的文件名列表。

fnmatch_filter.py

import fnmatch
import os
import pprint

pattern = 'fnmatch_*.py'
print('Pattern :', pattern)

files = list(sorted(os.listdir('.')))

print('\nFiles   :')
pprint.pprint(files)

print('\nMatches :')
pprint.pprint(fnmatch.filter(files, pattern))

这个例子中,filter() 返回了与这部分相关的示例源文件名列表。

$ python3 fnmatch_filter.py

Pattern : fnmatch_*.py

Files   :
['fnmatch_filter.py',
 'fnmatch_fnmatch.py',
 'fnmatch_fnmatchcase.py',
 'fnmatch_translate.py',
 'index.rst']

Matches :
['fnmatch_filter.py',
 'fnmatch_fnmatch.py',
 'fnmatch_fnmatchcase.py',
 'fnmatch_translate.py']

翻译模式

在内部,fnmatch() 将 glob 模式转为一个正则表达式,然后使用  re 模块比较文件名和模式。translate() 方法是一个公共的 API 用于将 glob 模式转换为正则表达式。

fnmatch_translate.py

import fnmatch

pattern = 'fnmatch_*.py'
print('Pattern :', pattern)
print('Regex   :', fnmatch.translate(pattern))

为了创建一个有效的正则表达式,一些特殊字符将会被转义。

$ python3 fnmatch_translate.py

Pattern : fnmatch_*.py
Regex   : (?s:fnmatch_.*\.py)\Z

推荐阅读

  • fnmatch标准库文档
  • glob -- glob 模块将 fnmatch()os.listdir() 合并产生一个匹配模式的列表。
  • re -- 正则表达式模式匹配。