如何使用 grep GZ 文件来提取 PNG 文件?

How do I grep GZ files to extract PNG files?

好的,所以我在一个文件夹中有一些 .GZ 文件,我希望递归地查看每个文件并将所有 PNG 文件提取到另一个目标文件夹中。我该怎么做?

编辑:

我一直在终端使用此命令在 GZ 文件中查找字符串并将整个文件复制到另一个目标目录。然后用它做事。有一些缺点。第一,当我输入 "PNG" 时,它会找到引用 "PNG" 而不是文件类型的文件,例如 CSS 文件。其次,除了复制整个文件外,它不会向目录输出任何内容。我想提取文件。

find . -type f -print0 | xargs -0 grep -lh "png" | xargs -I % cp % /some_destination

编辑:

这是一个示例文件夹结构:

FILE001.GZ, FILE002.GZ, FILE003.GZ, etc

并非所有文件都包含 PNG,其中一些包含文件夹结构中的许多文件。我想要的是另一个目标文件夹中的以下内容:

34950560.png, 3959560.png, etc.

提前致谢!

您可以使用文件签名(又名幻数)。 PNG 文件的前几个字节包含一个文件签名,表明该文件是 PNG。如果文件都是 gzip 压缩的,那么 gzip 中会有一个额外的 header,我们可以跳过它。
od 是一个命令,它将以您指定的可读格式转储文件的一部分。我告诉它跳过 gzip header 并以十六进制格式转储。根据我的测试,您将在接下来的八个字节中得到一个字符串“34e6 5580”。如果匹配PNG签名,将其移动到新目录并重命名。

COUNTER=0; mkdir PNGDIR
#
for FILE in `ls -1d *`; do  
   od -j 4 -N 10 -x ${FILE} | grep -q "34e6 5580" 
   if [ $? -eq 0 ]; then
     COUNTER=`expr 1 + $COUNTER`
     cp ${FILE} PNGDIR/picture_${COUNTER}.png.gz
   fi
done

假设您的“.GZ”文件实际上是包含多个文件的“.tar”压缩包,那么您可以一行完成您的目标:

find . -type f -iname '*.GZ' | xargs -n1 -I'{}' tar -C "/path/to/extract" -xf '{}' '*.png' 2>/dev/null

解释:

  • find . -type f -iname '*.GZ' :查找当前路径(包括子目录)中的所有 .GZ 文件。 -iname表示不区分大小写,同时匹配.gz和.GZ文件
  • xargs -n1 -I'{}' <command> '{}' : 从 stdin 调用 'command' 至多一个参数 (-n1),将参数放在占位符 {}.
  • tar -C "/path/to/extract" -xf '{}' '*.png' :从 xargs (-xf {}) 获得的文件中提取,只有以“*.png”结尾的文件。 -C /path/to/extract: 在那里提取文件。
  • 2>/dev/null : 忽略从不包含 .png 文件的 GZ 文件引发的错误消息。

此命令将提取指定文件夹中的所有 .png 个文件(保留原始 tar.gz 个文件中的任何目录结构)。跨多个存档的同名 .png 文件将仅存储一次,即最后提取的 .png 文件将覆盖之前的同名文件。 如果你想克服这个问题,那么你需要一个更复杂的脚本,比如:

#!/usr/bin/bash

function extract_png() {
    local gzpath=; local extract_path=
    cd "$gzpath" || return 2
    find . -iname '*.GZ' | 
        while read gzfile; do
            if tar -tf "$gzfile" '*.png' 2>/dev/null; then
                local basename=${gzfile%.*}; basename=${basename##*/}
                local extract_to="$extract_path/$basename"
                mkdir -p "${extract_to}"
                tar -C "$extract_to" -xf "$gzfile" '*.png'
            fi
        done
}

extract_png '/path/to/search' '/path/to/save'

extract_png 函数会将提取的 .png 文件保存到每个存档的不同子文件夹中,在 /path/to/save 下(例如 /path/to/save/FILE001//path/to/save/FILE002/ 等) .

关于 if tar -tf "$gzfile" '*.png' 2>/dev/null; then ... 的解释:如果文件“$gzfile”中有 .png 文件,这将 return 为真。 tar 中的 -t 参数表示 "list contents"。当指定文件 (*.png) 未包含在存档中时,tar -t 打印一条错误消息(被 2>/dev/null 隐藏)和 returns 一个非零代码来评估这个条件为假。