У меня есть каталог с подкаталогами. В каталогах много картинок, отсканированных из интернета.

Как мне просмотреть все файлы и показать те файлы, которые не являются допустимыми файлами изображений?

Он не должен основываться на расширении файла.

Я придумал этот сценарий:

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

Но это не работает, потому что он выводит достоверные изображения тоже.

2 ответа2

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 завершается успешно, если файл на самом деле не является изображением. Путь затем печатается.

Заметки:

  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/) нарушают логику.

0

Вы должны сделать это, проверив подписи типов файлов. Его можно найти здесь, или вы можете найти его методом проб и ошибок, проверяя ваши файлы.

Например, подпись JPG - это FF D8 FF E0 , что означает, что первые четыре байта должны быть равны FF D8 FF E0 .

Все, что вам нужно, это инструмент для сопоставления этих байтов с байтами файла. Например, hexdump -n 4 -C file.jpg| awk '{print $2 $3 $4 $5}' возвращает эти байты в шестнадцатеричном формате, которые можно сравнить с желаемой сигнатурой.

Если у вас есть испорченные файлы изображений, дополнительную информацию о сигнатурах файлов и восстановлении можно найти здесь. Например, когда загружается только часть изображения.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .