在 Linux 上忽略 glob() 中的大小写

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8151300/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 21:49:13  来源:igfitidea点击:

Ignore case in glob() on Linux

pythonlinux

提问by andreas-h

I'm writing a script which will have to work on directories which are modified by hand by Windows and Linux users alike. The Windows users tend to not care at all about case in assigning filenames.

我正在编写一个脚本,该脚本必须处理由 Windows 和 Linux 用户手动修改的目录。Windows 用户往往根本不关心分配文件名的大小写。

Is there a way to handle this on the Linux side in Python, i.e. can I get a case-insensitive, glob-like behaviour?

有没有办法在 Python 的 Linux 端处理这个问题,即我可以获得不区分大小写的类似 glob 的行为吗?

采纳答案by Fred Foo

Use case-insensitive regexes instead of glob patterns. fnmatch.translategenerates a regex from a glob pattern, so

使用不区分大小写的正则表达式而不是 glob 模式。fnmatch.translate从 glob 模式生成一个正则表达式,所以

re.compile(fnmatch.translate(pattern), re.IGNORECASE)

gives you a case-insensitive version of a glob pattern as a compiled RE.

为您提供一个不区分大小写的 glob 模式版本作为已编译的 RE。

Keep in mind that, if the filesystem is hosted by a Linux box on a Unix-like filesystem, users will be able to create files foo, Fooand FOOin the same directory.

请记住,如果文件系统是由一台Linux机器上托管一个类Unix文件系统,用户将能够创建文件fooFooFOO在同一目录下。

回答by Geoffrey Irving

You can replace each alphabetic character c with [cC], via

您可以用 [cC] 替换每个字母字符 c,通过

import glob
def insensitive_glob(pattern):
    def either(c):
        return '[%s%s]' % (c.lower(), c.upper()) if c.isalpha() else c
    return glob.glob(''.join(map(either, pattern)))

回答by Raffi

Non recursively

非递归

In order to retrieve the files (and files only) of a directory "path", with "globexpression":

为了检索目录“path”的文件(和仅文件),使用“globexpression”:

list_path = [i for i in os.listdir(path) if os.path.isfile(os.path.join(path, i))]
result = [os.path.join(path, j) for j in list_path if re.match(fnmatch.translate(globexpression), j, re.IGNORECASE)]

Recursively

递归地

with walk:

步行:

result = []
for root, dirs, files in os.walk(path, topdown=True):
  result += [os.path.join(root, j) for j in files \
             if re.match(fnmatch.translate(globexpression), j, re.IGNORECASE)]

Better also compile the regular expression, so instead of

最好也编译正则表达式,而不是

re.match(fnmatch.translate(globexpression)

do (before the loop):

做(在循环之前):

reg_expr = re.compile(fnmatch.translate(globexpression), re.IGNORECASE)

and then replace in the loop:

然后在循环中替换:

  result += [os.path.join(root, j) for j in files if re.match(reg_expr, j)]

回答by HCLivess

Depending on your case, you might use .lower()on both file pattern and results from folder listing and only then compare the pattern with the filename

根据您的情况,您可以同时使用.lower()文件模式和文件夹列表的结果,然后才将模式与文件名进行比较