У меня есть каталог с подкаталогами. В каталогах находится множество изображений, взятых из Интернета.
Как мне перебрать все файлы и отобразить те из них, которые не являются допустимыми файлами изображений?
Он не должен основываться на расширении файла.
Я придумал такой сценарий:
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
, что означает, что ее первые четыре байта должны быть равны 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, чтобы проверить, является ли изображение действительным, но даже в этом случае его можно подделать! Так что идеального способа проверки нет.