サブディレクトリのあるディレクトリがあります。ディレクトリには、Web からクロールされた画像が多数あります。
すべてのファイルをループして、有効な画像ファイルではないファイルを表示するにはどうすればよいですか?
ファイル拡張子に基づいてはなりません。
私は次のようなスクリプトを思いつきました:
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
ファイルに対してカスタム テストを実行します。パイプを構築するにはシェルが必要です。適切な拡張子を持つファイルごとに個別のシェルが実行されるため、ソリューションのパフォーマンスはかなり低くなります。
シェルは を実行しfile -b --mime-type
、grep
結果が . で始まるかどうかを確認しますimage/
。!
パイプの先頭は終了ステータスを否定するため、-exec
ファイルが実際には画像でない場合のみ、テスト全体が成功します。次に、パスが出力されます。
ノート:
- すべてのファイルをチェックするにはテストを省略します
-name
。 -iname
または、の代わりにを使用することもできます-name
。-iname
ただし、POSIX では必須ではありません。のオプション-b
も必須ではありません。--mime-type
file
次の出力は少し異なりますが、より高速です。
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
、最初の 4 バイトは と等しくなければならないことを意味しますFF D8 FF E0
。
必要なのは、これらのバイトをファイルのバイトと一致させるツールだけです。たとえば、hexdump -n 4 -C file.jpg| awk '{print $2 $3 $4 $5}'
これらのバイトを 16 進形式で返し、目的の署名と比較することができます。
画像ファイルが壊れている可能性がある場合は、ファイルの署名と回復に関する詳細情報を参照してください。ここたとえば、画像の一部だけがダウンロードされる場合などです。
答え3
ファイル拡張子とマジックバイトのチェックは簡単に偽装できます。https://unix.stackexchange.com/questions/189364/script-to-determine-if-apparent-image-files-are-real-image-files/189367#189367参考までに、基本的には imagemagick を使用して画像が有効かどうかを確認しますが、それでも偽装される可能性があります。したがって、確認する完璧な方法はありません。