在 python 中将普通文件名与 fnmatch 模式分开

Posted

技术标签:

【中文标题】在 python 中将普通文件名与 fnmatch 模式分开【英文标题】:Separate plain filenames from fnmatch patterns in python 【发布时间】:2014-04-06 11:31:01 【问题描述】:

我的 python 函数有一个(长)路径参数列表,每个参数都可能是一个 glob。我使用glob.glob 遍历此列表以提取所有匹配的文件名,如下所示:

files  = [filename for pattern in patterns for filename in glob.glob(pattern)]

这行得通,但是我所在的文件系统对于目录列表操作的性能非常差,目前这个操作增加了我的程序启动时间大约一分钟(!)。因此,我只想对非平凡的 glob 模式(即那些不仅仅是普通路径名的模式)执行 glob 扩展以加快速度。即

def cheapglob(pattern):
    return [pattern] if istrivial(pattern) else glob.glob(pattern)
files  = [filename for pattern in patterns for filename in cheapglob(pattern)]

由于glob.glob 基本上是一组目录列表加上fnmatch.fnmatch,我认为应该可以以某种方式询问fnmatch 给定的字符串是否是一个重要的模式,但我不能看看怎么做。

作为后备,我想我可以尝试自己识别字符串中的这些模式,尽管这感觉很像重新发明***,而且容易出错。但这感觉像是应该有一个优雅的解决方案。

【问题讨论】:

【参考方案1】:

根据the fnmatch source code,它唯一识别的特殊字符是*?[]。因此,任何不包含这些的任何模式都只会匹配自己。因此,我们可以将问题中提到的cheapglob 实现为

def cheapglob(s): return glob.glob(s) if re.search("[][*?]", s) else [s]

这只会命中包含特殊字符的模式的文件系统。这与普通的 glob.glob 略有不同:对于没有特殊字符(如“foo.txt”)的模式,无论该文件是否存在,此函数都将返回 ["foo.txt"],而如果文件存在,glob.glob 将返回 []不在那里。所以调用函数需要处理一些返回的文件可能不存在的可能性。

【讨论】:

【参考方案2】:

我不认为你会发现很多,因为你对微不足道的模式的想法可能不是我的。此外,从 comp-sci 的角度来看,可能无法通过检查判断下推自动机是否会在给定您正在运行的输入的情况下在设定的时间内运行,而无需实际针对这些输入运行它.

我强烈怀疑您最好在这里加载目录列表一次,然后手动对该列表应用fnmatch

【讨论】:

那么“一个没有fnmatch 识别为特殊字符的模式”怎么样?那些只会匹配自己。这是一个定义明确的问题。我没有一个目录可以一劳永逸地列出。那不会是一个问题。在我在问题中提到的 1 分钟运行时间内,每个目录已经只列出一次。他们只有很多,而且每个列表都很慢。

以上是关于在 python 中将普通文件名与 fnmatch 模式分开的主要内容,如果未能解决你的问题,请参考以下文章

.gitignore 样式 fnmatch()

Python3标准库:fnmatch UNIX式glob模式匹配

python--fnmatch

Python 2.7 fnmatch 不编辑文本

获取与 fnmatch 不匹配的元素

part12:Python 文件I/O(pathlib模块:PurePathPath,os.path,fnmatch,open,with,linecache,os模块操作文件和目录,tempfile(