你会如何实施的蚂蚁式patternsets python选择群体的文件?
题
只蚂蚁都有一个很好的方式来选择组的文件,最轻易使用**指示目录树。E.g。
**/CVS/* # All files immediately under a CVS directory.
mydir/mysubdir/** # All files recursively under mysubdir
更多的例子可以在这里看到:
http://ant.apache.org/manual/dirtasks.html
你会如何实现这蟒蛇,这样你可以做一些事情,如:
files = get_files("**/CVS/*")
for file in files:
print file
=>
CVS/Repository
mydir/mysubdir/CVS/Entries
mydir/mysubdir/foo/bar/CVS/Entries
解决方案
只要你遇到一个 **
, 你们要recurse通过的整体目录的结构,因此,我认为在这一点上,最简单的方法是循环,通过目录的操作系统。走路,建造一条路径,然后检查,如果有匹配的模式。你也许可以转换为一个regex通过这样的:
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
, 以及具有只是 \*\*
来比赛的尾部。)
然而,很显然你不想recurse通过下面的一切现dir时不处理一个 **
图案,因此我认为你需要一个两阶段的做法。我没有试图实施以下,并有可能的几个角落的情况,但我认为它应当工作:
分裂纹在你的目录分离.即
pat.split('/') -> ['**','CVS','*']
Recurse通过目录,并期待在相关模式的一部分用于这个水平。ie。
n levels deep -> look at pat[n]
.如果
pat[n] == '**'
关于上述战略:- 重建的图案
dirsep.join(pat[n:])
- 转换到一个与regex
glob\_to\_regex()
- 递归
os.walk
通过当前的目录,建立起路径相对水平,你开始。如果路相匹配的regex,产率。
- 重建的图案
如果帕特不匹配
"**"
, ,这是最后一个元素中的模式,则产量的所有文件/dirs匹配glob.glob(os.path.join(curpath,pat[n]))
如果帕特不匹配
"**"
, 和不是最后的元素中的模式,然后为每个目录,检查其是否符合(用滴)pat[n]
.如果是这样,recurse下通过它,增加深度(此它将看看pat[n+1]
)
其他提示
对不起,这是你的OP后很长一段时间。我刚刚发布了一个Python包,它正是这样做的 - 它叫做Formic,它可以在 PyPI Cheeseshop 。使用Formic,您的问题可通过以下方式解决:
import formic
fileset = formic.FileSet(include="**/CVS/*", default_excludes=False)
for file_name in fileset.qualified_files():
print file_name
有一个轻微的复杂性:default_excludes。 Formic,就像Ant一样,默认情况下排除CVS目录(因为大多数情况下从构建文件中收集文件是危险的),问题的默认答案将导致没有文件。设置default_excludes = False会禁用此行为。
os.walk
是你的朋友。查看Python手册中的示例
( https://docs.python.org/2/library/os .html#os.walk )并尝试从中构建一些东西。
匹配“ ** / CVS / *
”根据您获得的文件名,您可以执行以下操作:
def match(pattern, filename):
if pattern.startswith("**"):
return fnmatch.fnmatch(file, pattern[1:])
else:
return fnmatch.fnmatch(file, pattern)
在 fnmatch.fnmatch
中," *"匹配任何东西(包括斜杠)。
'waf'构建系统源代码中有一个实现。 http://code.google的.com / p / WAF /源/浏览/中继/ waflib / Node.py R = 10755#471 可能这应该包含在自己的库中吗?
os.walk 是您最好的选择为了这。我用.svn做了下面的例子,因为我有这个方便,而且效果很好:
import re
for (dirpath, dirnames, filenames) in os.walk("."):
if re.search(r'\.svn, dirpath):
for file in filenames:
print file