[英]fnmatch and recursive path match with `**`
Is there any built-in or straightforward way to match paths recursively with double asterisk, eg like zsh does?是否有任何内置或直接的方法来递归匹配双星号的路径,例如像zsh那样?
For example, with例如,与
path = 'foo/bar/ham/spam/eggs.py'
I can use fnmatch to test it with我可以使用fnmatch来测试它
fnmatch(path, 'foo/bar/ham/*/*.py'
Although, I would like to be able to do:虽然,我希望能够做到:
fnmatch(path, 'foo/**/*.py')
I know that fnmatchmaps its pattern to regex , so in the words case I can roll my own fnmatch with additional **
pattern, but maybe there is an easier way我知道 fnmatch将其模式映射到 regex ,所以在单词的情况下,我可以使用额外的
**
模式滚动我自己的 fnmatch,但也许有更简单的方法
If you look into fnmatch source code closely, it internally converts the pattern to a regular expression, mapping *
into .*
(and not [^/]*
or similar) and thus does not care anything for directory separators /
- unlike UNIX shells:如果您仔细查看 fnmatch 源代码,它会在内部将模式转换为正则表达式,将
*
映射到.*
(而不是[^/]*
或类似的),因此不关心目录分隔符/
- 与 UNIX shell 不同:
while i < n:
c = pat[i]
i = i+1
if c == '*':
res = res + '.*'
elif c == '?':
res = res + '.'
elif c == '[':
...
Thus因此
>>> fnmatch.fnmatch('a/b/d/c', 'a/*/c')
True
>>> fnmatch.fnmatch('a/b/d/c', 'a/*************c')
True
If you can live without using an os.walk loop, try:如果您可以不使用 os.walk 循环,请尝试:
I personally use glob2:我个人使用 glob2:
import glob2
files = glob2.glob(r'C:\Users\**\iTunes\**\*.mp4')
As of Python 3.5, the native glob module supports recursive pattern matching:从 Python 3.5 开始,本机glob模块支持递归模式匹配:
import glob
files = glob.iglob(r'C:\Users\**\iTunes\**\*.mp4', recursive=True)
For an fnmatch variant that works on paths, you can use a library called wcmatch which implements a globmatch
function that matches a path with the same logic that glob
crawls a filesystem with.对于适用于路径的 fnmatch 变体,您可以使用名为wcmatch的库,该库实现了
globmatch
函数,该函数匹配具有与glob
抓取文件系统相同的逻辑的路径。 You can control the enabled features with flags, in this case, we enable GLOBSTAR
(using **
for recursive directory search).您可以使用标志控制启用的功能,在这种情况下,我们启用
GLOBSTAR
(使用**
进行递归目录搜索)。
>>> from wcmatch import glob
>>> glob.globmatch('some/file/path/filename.txt', 'some/**/*.txt', flags=glob.GLOBSTAR)
True
This snippet adds compatibility for **此代码段增加了对 ** 的兼容性
import re
from functools import lru_cache
from fnmatch import translate as fnmatch_translate
@lru_cache(maxsize=256, typed=True)
def _compile_fnmatch(pat):
# fixes fnmatch for recursive ** (for compatibilty with Path.glob)
pat = fnmatch_translate(pat)
pat = pat.replace('(?s:.*.*/', '(?s:(^|.*/)')
pat = pat.replace('/.*.*/', '.*/')
return re.compile(pat).match
def fnmatch(name, pat):
return _compile_fnmatch(str(pat))(str(name)) is not None
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.