我有数百个 zip 文件,想在其中找到特定的文件。文件名的 grep 相当简单:
find . -name "*.zip" -exec unzip -Z -1 {} \; | grep png
这将给出zip 文件中的所有文件名。例如
icons/full/obj16/folder.png
icons/full/obj16/folderType_filter.png
icons/full/wizban/newfolder_wiz.png
但是如何在每一行前面加上 zip 文件的名称,这样我才能真正找到它?像这样:
dir1/a.zip:icons/full/obj16/folder.png
dir2/icons.zip:icons/full/obj16/folderType_filter.png
myicons.zip:icons/full/wizban/newfolder_wiz.png
运行这个:
解释:
-type f
以防某些目录(或其他不是常规文件的文件)意外匹配-name "*.zip"
. 我不想尝试unzip
目录。find -exec
来为每个由find
.-exec … {} +
用来生成的 shell 远远少于每个文件一个。现在单个 shell 可以获取多个路径作为命令行参数,我用for
.grep
表达式awk
。如果我将它们嵌入到 shell 代码中,那么我需要使用额外的转义和/或引用来混淆命令。单独传递表达式要干净得多。我可以将它们作为命令行参数传递给sh
,但是我需要将它们保存在内壳的变量中,并且shift
在我可以循环实际路径之前正确地保存它们(仍然比引用疯狂的 IMO 更好)。find-sh
在这里解释:什么是第二个 shsh -c 'some shell code' sh
?grep -i
。grep
只是png
,它可以匹配例如stopngo
。我将它固定在行尾并添加了一个前导点。点需要转义,因为未转义.
匹配正则表达式中的任何字符。awk
将当前处理的文件(和:
)的路径添加到从grep
. 有人可能会认为shell 扩展的sed "s|^|$f:|"
地方$f
会起作用;但是随后的扩展$f
可能会破坏表达式(想象它包含|
,代码注入是可能的)。如果我让 shell$f
在awk
代码中扩展,它也会有类似的缺陷。随着awk -v "f=$f"
我将路径存储为f
变量awk
(注意awk
变量和shell变量是独立的概念)。现在不能破坏代码,因为f
知道它不是代码。此外,为整个表达式设计的是静态的,所以我可以首先在环境中传递它。awk
awk
awk