gpt4 book ai didi

Python,如何实现类似 .gitignore 的行为

转载 作者:太空狗 更新时间:2023-10-29 20:56:10 25 4
gpt4 key购买 nike

我需要列出当前目录 (.)(包括所有子目录)中的所有文件,并排除一些文件作为 .gitignore 的工作方式 (http://git-scm.com/docs/gitignore)

使用 fnmatch ( https://docs.python.org/2/library/fnmatch.html ) 我将能够使用模式“过滤”文件

ignore_files = ['*.jpg', 'foo/', 'bar/hello*']
matches = []
for root, dirnames, filenames in os.walk('.'):
for filename in fnmatch.filter(filenames, '*'):
matches.append(os.path.join(root, filename))

我如何“过滤”并获取与我的“ignore_files”中的一个或多个元素不匹配的所有文件?

谢谢!

最佳答案

你在正确的轨道上:如果你想使用 fnmatch 风格的模式,你应该使用 fnmatch.filter和他们在一起。

但是有三个问题使这不是很微不足道。

首先,您要应用多个过滤器。你是怎样做的?多次调用filter:

for ignore in ignore_files:
filenames = fnmatch.filter(filenames, ignore)

其次,您实际上想要执行 filter反向:返回匹配的名称子集。如文档所述:

It is the same as [n for n in names if fnmatch(n, pattern)], but implemented more efficiently.

因此,相反,您只需输入 not:

for ignore in ignore_files:
filenames = [n for n in filenames if not fnmatch(n, ignore)]

最后,您尝试过滤部分路径名,而不仅仅是文件名,但您直到过滤后才执行 join。所以调换顺序:

filenames = [os.path.join(root, filename) for filename in filenames]
for ignore in ignore_files:
filenames = [n for n in filenames if not fnmatch(n, ignore)]
matches.extend(filenames)

有几种方法可以改善这一点。

您可能希望使用生成器表达式而不是列表推导式(圆括号而不是方括号),因此如果您有大量文件名列表,您可以使用惰性管道而不是浪费时间和空间重复构建大量列表。

此外,如果您颠倒循环的顺序,可能会或可能不会更容易理解,如下所示:

filenames = (n for n in filenames 
if not any(fnmatch(n, ignore) for ignore in ignore_files))

最后,如果你担心性能,你可以在每个表达式上使用 fnmatch.translate 将它们变成等效的正则表达式,然后将它们合并成一个大的正则表达式并编译它,然后使用它而不是围绕 fnmatch 的循环。如果允许您的模式比 *.jpg 更复杂,这可能会变得棘手,除非您确实在此处确定了性能瓶颈,否则我不会推荐它。但如果您需要这样做,我至少看到一个关于 SO 的问题,其中有人付出了很多努力来敲定所有边缘情况,所以搜索而不是尝试自己编写。

关于Python,如何实现类似 .gitignore 的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25229592/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com