在多个 zip 文件中搜索文件

在多个 zip 文件中搜索文件

我有数百个 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

答案1

运行这个:

gexp='\.png$' aexp='{print f":"$0}' find . -type f -name "*.zip" -exec sh -c '
   for f do
      unzip -Z -1 "$f" | grep -i "$gexp" | awk -F "" -v "f=$f" "$aexp"
   done
' find-sh {} +

解释:

  • 我使用-type f以防某些目录(或其他非常规文件)意外匹配-name "*.zip"。我不想尝试unzip目录。
  • find -exec我使用从调用的shell为每个文件运行自定义管道由 预选find
  • 我过去-exec … {} +为每个文件生成远少于一个的 shell。现在,单个 shell 可以将多个路径作为命令行参数,我使用 循环遍历它们for
  • 我传递了我想在环境中使用的静态表达式grepawk如果我将它们嵌入到 shell 代码中,那么我需要使用额外的转义和/或引号来混淆命令。单独传递表达式要干净得多。我可以将它们作为命令行参数传递给sh,但随后我需要将它们保存在内壳的变量中,shift然后才能循环实际路径(在我看来,这仍然比引用狂热要好)。
  • find-sh解释如下:中的第二个 sh 是什么sh -c 'some shell code' sh
  • 我使用不区分大小写grep -i
  • 您的模式grep只是png,它可以匹配例如stopngo。我将其固定在行尾并添加了前导点。该点需要转义,因为未转义.匹配正则表达式中的任何字符。
  • awk将当前处理的文件(和)的路径添加:到从 管道传输的每一行的开头grep。有人可能会认为shellsed "s|^|$f:|"扩展$f的 会起作用;但是 的扩展$f可能会破坏表达式(假设它包含|,则代码注入是可能的)。如果我让 shell$fawk代码中扩展,它也会同样存在缺陷。awk -v "f=$f"我将路径作为f变量存储在 中awk(注意awk变量和 shell 变量是独立的概念)。现在fawk不能破坏代码,因为awk知道它不是代码。此外,为 设计的整个表达式awk是静态的,所以我可以首先将它传递到环境中。

相关内容