尽管 glob API 很少,但是功能强大。在那种需要查找系统上匹配一个模式的文件时非常有用。当需要去创建一个有某个相同扩展,前缀或者中间有共同字符串的文件列表时,应该考虑使用 glob 而不是自定义处理目录内容的代码。
glob 模块使用的模式规则不同于 re 模块使用的正则表达式。而是使用 Unix 路径扩展规则。只有少数特殊字符用去实现两个不同的通配符以及特殊字符。模式规则应用于文件名的段(以路径分隔符 / 为界)。模式中的路径可以是相对的或者绝对的。Shell 变量名和波浪符( ~ )不会被展开。
示例数据
假设这个例子中的测试文件是存在于当前工作目录的。
$ python3 glob_maketestdata.py dir dir/file.txt dir/file1.txt dir/file2.txt dir/filea.txt dir/fileb.txt dir/file?.txt dir/file*.txt dir/file[.txt dir/subdir dir/subdir/subfile.txt
如果这些文件不存在,请在运行接下来例子之前使用示例代码中的 glob_maketestdata.py 创建它们。
通配符
一个星号( * )匹配名称片段中零个或者多个字符,例如,dir/*。
glob_asterisk.py import glob for name in sorted(glob.glob('dir/*')): print(name)
这个模式匹配 「 dir 」目录中的每个路径名称(文件或者目录),但是不会进一步递归遍历子目录。glob 返回的数据是没有排序的,所以例子中对它进行排序以便更清楚地研究结果。
$ python3 glob_asterisk.py dir/file*.txt dir/file.txt dir/file1.txt dir/file2.txt dir/file?.txt dir/file[.txt dir/filea.txt dir/fileb.txt dir/subdir
如果要查看子目录的内容,子目录必须包含在模式中。
glob_subdir.py import glob print('Named explicitly:') for name in sorted(glob.glob('dir/subdir/*')): print(' {}'.format(name)) print('Named with wildcard:') for name in sorted(glob.glob('dir/*/*')): print(' {}'.format(name))
前面显示的第一个例子中显示地列出了子目录名称,但是第二个依赖于通配符查找子目录。
$ python3 glob_subdir.py Named explicitly: dir/subdir/subfile.txt Named with wildcard: dir/subdir/subfile.txt
在这个示例中两种方式的结果是一样的。但是如果这里还有一个子目录,通配符将会匹配这两个子目录并包含这两个目录下的所有文件。
单字符通配符
问好( ? )是另一个通配符。它匹配文件名称中任何单个字符。
glob_question.py import glob for name in sorted(glob.glob('dir/file?.txt')): print(name)
前面的例子中匹配所有以 file 开始的文件,紧接着是一个任何类型的字符,然后以 .txt 结束。
$ python3 glob_question.py dir/file*.txt dir/file1.txt dir/file2.txt dir/file?.txt dir/file[.txt dir/filea.txt dir/fileb.txt
字符范围
使用字符范围( [a-z] )而不是问号去匹配多个字符中的一个。这个例子中将会查找到所有在扩展名之前有一个数字的文件。
glob_charrange.py import glob for name in sorted(glob.glob('dir/*[0-9].*')): print(name)
字符范围 [0-9] 匹配一个数字。范围根据每个字母或者数字的字符代码进行排序,破折号表示字符的连续范围。[0-9] 等同于 [0123456789] 。
$ python3 glob_charrange.py dir/file1.txt dir/file2.txt
转义元字符
有时候可能需要去查找一些包含 glob 模式使用的特殊字符的文件。escape() 方法会用转义后的特殊字符构建一个适配模式,这样 glob 就不会将它当做特殊字符解释处理。
glob_escape.py import glob specials = '?*[' for char in specials: pattern = 'dir/*' + glob.escape(char) + '.txt' print('Searching for: {!r}'.format(pattern)) for name in sorted(glob.glob(pattern)): print(name) print()
通过构建包含单个字符的字符范围将每个特殊字符进行转义。
$ python3 glob_escape.py Searching for: 'dir/*[?].txt' dir/file?.txt Searching for: 'dir/*[*].txt' dir/file*.txt Searching for: 'dir/*[[].txt' dir/file[.txt