对于平台无关的应用程序,使 pathlib.glob() 和 pathlib.rglob() 不区分大小写

alb*_*ert 5 python cross-platform glob case-sensitive pathlib

我正在使用pathlib.glob()pathlib.rglob()分别匹配目录及其子目录中的文件。目标文件都是小写.txt和大写.TXT文件。从文件系统读取相应的文件路径,如下所示:

import pathlib

directory = pathlib.Path()
files_to_create = ['a.txt', 'b.TXT']
suffixes_to_test = ['*.txt', '*.TXT']

for filename in files_to_create:
    filepath = directory / filename
    filepath.touch()
    
for suffix in suffixes_to_test:
    files = [fp.relative_to(directory) for fp in directory.glob(suffix)]
    print(f'{suffix}: {files}')
Run Code Online (Sandbox Code Playgroud)

大部分代码库是在 Windows 10 计算机(运行 Python 3.7.4)上开发的,现在已转移到 macOS Monterey 12.0.1(运行 Python 3.10.1)。

在 Windows 上,两个文件a.txtb.TXT都匹配模式:

*.txt: [WindowsPath('a.txt'), WindowsPath('b.TXT')]
*.TXT: [WindowsPath('a.txt'), WindowsPath('b.TXT')]
Run Code Online (Sandbox Code Playgroud)

相比之下,macOS 只有一个文件与每种模式匹配:

*.txt: [PosixPath('a.txt')]
*.TXT: [PosixPath('b.TXT')]
Run Code Online (Sandbox Code Playgroud)

因此,我假设 macOS 文件系统可能区分大小写,而 Windows 则不区分大小写。根据Apple 的用户指南,默认情况下使用的 macOS 文件系统不应区分大小写,但可以如此配置。类似的情况可能适用于 Linux 或 Unix 文件系统,如此此处所讨论的。

尽管存在这种不同行为的原因,但我需要找到一种与平台无关的方法来获取大写TXT和小写txt文件。一个相当幼稚的解决方法可能是这样的:

results = set([fp.relative_to(directory) for suffix in suffixes_to_test for fp in directory.glob(suffix)])
Run Code Online (Sandbox Code Playgroud)

这在 macOS 和 Windows 上都给出了所需的输出:

{PosixPath('b.TXT'), PosixPath('a.txt')}
Run Code Online (Sandbox Code Playgroud)

然而,有没有更优雅的方式呢?我找不到像pathlib 文档ignore_case中那样的任何选项。

Chr*_*lly 3

怎么样:

suffix = '*.[tT][xX][tT]'
files = [fp.relative_to(directory) for fp in directory.glob(suffix)]
Run Code Online (Sandbox Code Playgroud)

对于“不区分大小写的 glob”来说,它并不是那么通用,但它对于有限和特定的用例(例如特定扩展的 glob)来说效果很好。