我如何找到无效的图像?

我如何找到无效的图像?

我有一个带有子目录的目录。目录中有很多从网上爬来的图片。

我如何循环遍历每个文件并显示那些不是有效图像文件的文件?

它不应该基于文件扩展名。

我想出了这个脚本:

find . -name '*.jpg' -o -name '*.jpeg' -o -name '*.gif' -o -name '*.png' | while read FILE; do
    if ! identify "$FILE" &> /dev/null; then
         echo "$FILE"
    fi  
done

但这不起作用,因为它也输出有效的图像。

答案1

find . -type f \
       \( -name '*.jpg' -o -name '*.jpeg' -o -name '*.gif' -o -name '*.png' \) \
       -exec sh -c '! file -b --mime-type "$1" | grep -q "^image/"' sh {} \; \
       -print

我的方法是使用-exec自定义测试来测试文件。需要一个 shell 来构建管道。每个具有正确扩展名的文件都会运行一个单独的 shell,因此该解决方案的性能相当差。

shell 运行file -b --mime-type,然后grep检查结果是否以image/.!开头,如果管道开头则否定其退出状态,因此-exec如果文件不是真正的图像,则整个测试成功。然后打印路径。

笔记:

  1. 省略-name测试来检查所有文件。
  2. 或者您可能想使用-iname而不是-name
  3. -iname但 POSIX 并不要求 。 也不是-b--mime-type选项file
  4. 以下产生略有不同的输出并且速度更快:

    find . -type f \
           \( -name '*.jpg' -o -name '*.jpeg' -o -name '*.gif' -o -name '*.png' \) \
           -exec file --mime-type {} + \
    | grep -v "\bimage/"
    

    一些文件名(例如带有换行符)或路径(带有image/)会破坏逻辑。

答案2

您必须通过检查文件类型签名来执行此操作。可以找到这里,或者您可以通过反复试验检查文件来找到它。

例如JPG签名为FF D8 FF E0,即其前四个字节必须等于FF D8 FF E0

您所需要的只是一个工具来将这些字节与文件的字节进行匹配。例如,hexdump -n 4 -C file.jpg| awk '{print $2 $3 $4 $5}'以十六进制格式返回这些字节,可以将其与所需的签名进行比较。

如果您拥有的图像文件可能已损坏,可以找到有关文件签名和恢复的高级信息这里. 例如,当仅下载图像的一小部分时。

答案3

检查文件扩展名和魔法字节很容易被欺骗。请参阅https://unix.stackexchange.com/questions/189364/script-to-determine-if-apparent-image-files-are-real-image-files/189367#189367为了获得灵感,基本上使用 imagemagick 来检查图像是否有效,但即使这样也可能被欺骗!所以没有完美的检查方法。

相关内容