如何找到無效圖像?

如何找到無效圖像?

我有一個帶有子目錄的目錄。在目錄中,有許多從網路上爬取的圖像。

如何循環遍歷每個文件並顯示那些不是有效圖像文件的文件?

它不應該基於檔案副檔名。

我想出了這個腳本:

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 運行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-define-if-apparent-image-files-are-real-image-files/189367#189367為了獲得靈感,基本上使用 imagemagick 來檢查圖像是否有效,但即使這樣也可能被欺騙!所以沒有完美的檢查方法。

相關內容