Используйте поиск, чтобы удалить все изображения с заданными размерами
Я просто использовал Recuva и Photorec для восстановления некоторых данных со случайно отформатированного диска. Естественно, результатом является каждый неповрежденный файл, который когда-либо существовал на диске в течение его срока службы. Это означает десятки тысяч маленьких изображений значков, как PNG, так и JPG, которые я хотел бы удалить - скажем, все, что меньше 100 x 100 пикселей.
Есть решения из там, но все они довольно сложные и даже самые простые полагаться на трубопровод через несколько внешних программ и
rm
для фактического удаления. Это не идеально, потому что, когда вы делаете что-то достаточно часто в
bash
Я всегда предпочитаю однострочный текст, который я могу запомнить и каждый раз вводить в командной строке.
В эпоху гораздо более полноценного GNU
find
что идет с
-delete
, неужели нет возможности сделать это полностью или даже в основном внутри
find
сам?
РЕДАКТИРОВАТЬ: Если
find
не буду сокращать его, я также был бы рад использовать любой другой инструмент GNU.
1 ответ
В эпоху гораздо более полноценного GNU
find
что идет с-delete
, неужели нет возможности сделать это полностью или даже в основном внутриfind
сам?
find
не для чтения (мета) данных изображения (сравните "DOTADIW"). Чтобы выполнить произвольный тест, используйте
-exec
в качестве теста ( пример), а затем
-delete
. Это может быть так:
find . -type f -exec some_program -with -options -that -test -dimensions {} \; -delete
Iff
some_program
возвращает статус выхода
0
для файла тогда
-delete
пинает за файл.
Для более сложных тестов вам может понадобиться внутренняя оболочка:
find . -type f -exec sh -c 'shell-code "$1" | with-pipes && con-di-tio-nals -and -such' arbitrary-name {} \; -delete
Iff
sh
возвращает статус выхода
0
тогда
-delete
вступит в силу.
Одно большое преимущество: вы можете делать это безопасно, даже если в именах файлов есть символы новой строки, пробелы или специальные символы. Код надежный.
Один большой недостаток:
-exec … \;
будет работать один
some_program
на файл. Или один
sh
,
shell-code
,
with-pipes
и
con-di-tio-nals
на файл. Создание дополнительного процесса стоит дорого, поэтому этот подход может не сработать.
Чтобы смягчить этот недостаток, вы можете сразу передать больше имен файлов внутренней оболочке. Вот что делает этот ответ (код отлажен):
find . -iname "*.jpg" -type f -exec bash -c 'for i; do size=($(identify -format "%w %h" "$i")); (( size[0] < 300 || size[1] < 300 )) && rm -v "$i"; done' remove-files {} +
Запись
-exec … +
это не тест, который запустил бы
-delete
. Каждый процесс оболочки обрабатывает несколько файлов и возвращает единый статус выхода, так что это бесполезный тест для одного файла. Вместо,
rm
условно вызывается из оболочки.
Тем не менее будет один
identify
на файл и один
rm
на файл, который необходимо удалить. С другой стороны будет один
bash
на много файлов. Для хорошей производительности вы должны настоятельно предпочесть встроенные функции оболочки, арифметику оболочки и синтаксис оболочки над внешними исполняемыми файлами. Этот подход по-прежнему обрабатывает имена файлов безопасно и надежно.
Существуют инструменты, с помощью которых можно протестировать множество файлов за один процесс. Пример:
exiftool -q -r -if '$ImageHeight < 100' -if '$ImageWidth < 100' -p '$Directory/$FileName' .
(Это
exiftool
из
libimage-exiftool-perl
пакет в Debian. Решение взято из этого ответа.)
Обратите внимание, что эта конкретная команда не ограничивается "PNG и JPG".
Команда выводит такие результаты как
find . … -print
было бы. Затем вы можете подключиться к
xargs
звонить
rm
. Общие опасения по поводу путей трубопровода при применении текста, и я не уверен, что можно сделать
exiftool
вести себя как
find . … -print0
.
Таким образом, хотя это решение может хорошо работать, когда дело доходит до поиска файлов и печати их путей, это не самый надежный способ их фактического удаления без контроля человека.