一旦遇到 a **
,您将不得不遍历整个目录结构,所以我认为此时最简单的方法是使用 os.walk 遍历目录,构造路径,然后检查如果它与模式匹配。您可能可以通过以下方式转换为正则表达式:
def glob_to_regex(pat, dirsep=os.sep):
dirsep = re.escape(dirsep)
print re.escape(pat)
regex = (re.escape(pat).replace("\\*\\*"+dirsep,".*")
.replace("\\*\\*",".*")
.replace("\\*","[^%s]*" % dirsep)
.replace("\\?","[^%s]" % dirsep))
return re.compile(regex+"$")
(但请注意,这并不是功能齐全 -[a-z]
例如,它不支持样式 glob 模式,尽管这可能会被添加)。(第一个\*\*/
匹配是覆盖像\*\*/CVS
匹配这样的情况./CVS
,以及只\*\*
在尾部匹配。)
但是,显然你不想在不处理**
模式时递归当前目录下的所有内容,所以我认为你需要一个两阶段的方法。我没有尝试实现以下内容,并且可能存在一些极端情况,但我认为它应该可以工作:
在目录分隔符上拆分模式。IEpat.split('/') -> ['**','CVS','*']
递归遍历目录,并查看此级别模式的相关部分。IE。n levels deep -> look at pat[n]
.
如果pat[n] == '**'
切换到上述策略:
- 重构模式
dirsep.join(pat[n:])
- 转换为正则表达式
glob\_to\_regex()
- 递归
os.walk
地通过当前目录,建立相对于您开始的级别的路径。如果路径与正则表达式匹配,则生成它。
如果 pat 不匹配"**"
,并且它是模式中的最后一个元素,则产生所有匹配的文件/目录glob.glob(os.path.join(curpath,pat[n]))
如果 pat 不匹配"**"
,并且它不是模式中的最后一个元素,那么对于每个目录,检查它是否匹配 (with glob) pat[n]
。如果是这样,通过它向下递归,增加深度(所以它会看pat[n+1]
)