gpt4 book ai didi

python - Python 中的 "find . -regex ..."或如何查找全名(路径+名称)与正则表达式匹配的文件?

转载 作者:太空狗 更新时间:2023-10-29 18:33:05 24 4
gpt4 key购买 nike

我想找到其全名(相对的,虽然绝对也很好)匹配给定正则表达式的文件(即,像 glob 模块,但用于正则表达式匹配而不是 shell 通配符匹配).使用 find,例如:

find . -regex ./foo/\w+/bar/[0-9]+-\w+.dat

当然,我可以通过os.system(...)os.exec*(...) 使用find ,但我正在寻找纯 Python 解决方案。以下代码结合了 os.walk(...)re 模块正则表达式是一个简单的 Python 解决方案。 (它不够健壮,遗漏了许多(不那么极端的)极端情况,但足以满足的一次性使用目的,为一次性数据库插入定位特定数据文件。 )

import os
import re

def find(regex, top='.'):
matcher = re.compile(regex)
for dirpath, dirnames, filenames in os.walk(top):
for f in filenames:
f = os.path.relpath(os.path.join(dirpath, f), top)
if matcher.match(f):
yield f

if __name__=="__main__":
top = "."
regex = "foo/\w+/bar/\d+-\w+.dat"
for f in find(regex, top):
print f

但这是低效的。内容无法与正则表达式匹配的子树(例如,./foo/\w+/baz/,继续上面的示例)被不必要地遍历。理想情况下,这些子树应该从 walk 中剪掉;不应遍历路径名与正则表达式不部分匹配的任何子目录。 (我猜测 GNU find 实现了这样的优化,但我还没有通过测试或源代码细读来证实这一点。)

有谁知道基于正则表达式的健壮的 find 的 Python 实现,最好是子树修剪优化?我希望我只是缺少 os.path 模块或某些第三方模块中的方法。

最佳答案

来自 help(os.walk):

When topdown is true, the caller can modify the dirnames list in-place (e.g., via del or slice assignment), and walk will only recurse into the subdirectories whose names remain in dirnames; this can be used to prune the search...

因此,一旦某个子目录(列在dirnames 中)被确定为 Not Acceptable ,就应该将其从dirnames 中删除。这将产生您正在寻找的子树修剪。 (一定要先从尾端 dirnames del 项目,这样你就不会更改要删除的剩余项目的索引。)

import os
import re

def prune(regex,top='.'):
sep=os.path.sep
matcher = re.compile(regex)
pieces=regex.split(sep)
partial_matchers = map(
re.compile,
(sep.join(pieces[:i+1]) for i in range(len(pieces))))
for root, dirs, files in os.walk(top,topdown=True):
for i in reversed(range(len(dirs))):
dirname=os.path.relpath(os.path.join(root,dirs[i]), top)
dirlevel=dirname.count(sep)
# print(dirname,dirlevel,sep.join(pieces[:dirlevel+1]))
if not partial_matchers[dirlevel].match(dirname):
print('pruning {0}'.format(
os.path.relpath(os.path.join(root,dirs[i]), top)))
del dirs[i]

for filename in files:
filename=os.path.relpath(os.path.join(root,filename))
# print('checking {0}'.format(filename))
if matcher.match(filename):
print(filename)

if __name__=='__main__':
prune(r'foo/\w+/bar/\d+-\w+.dat')

运行具有如下目录结构的脚本:

~/test% tree .
.
|-- foo
| `-- baz
| |-- bad
| | |-- bad1.txt
| | `-- badbad
| | `-- bad2.txt
| `-- bar
| |-- 1-good.dat
| `-- 2-good.dat
`-- tmp
|-- 000.png
|-- 001.png
`-- output.gif

产量

pruning tmp
pruning foo/baz/bad
foo/baz/bar/2-good.dat
foo/baz/bar/1-good.dat

如果您取消注释“checking”打印语句,很明显修剪后的目录不会被遍历。

关于python - Python 中的 "find . -regex ..."或如何查找全名(路径+名称)与正则表达式匹配的文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6798097/

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