Есть ли способ найти файлы, содержащие только непечатаемые символы?

У меня есть программа, которая ведет себя плохо и создала несколько файлов с несколькими непечатаемыми символами. Если бы я должен был копировать файлы, я ничего не вижу (поскольку они не являются печатными символами). Тем не менее, эти файлы не будут отображаться, если я использую что-то вроде -empty или -empty -size 0 с помощью команды find .

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

С GNU grep (и несколькими другими реализациями grep) вы можете искать файлы, которые не содержат печатаемого символа. Опция -L означает список файлов, которые не содержат соответствия. [[:print:]] (да, есть две пары скобок) соответствует одному печатаемому символу; определение печатаемого персонажа зависит от вашего языка.

 grep -L '[[:print:]]' -- * 

Обратите внимание, что это включает в себя пустые файлы (как отметил ум ).

Чтобы удалить их все (сначала просмотрите вывод grep чтобы убедиться, что вы удаляете нужные файлы), предполагая, что имена файлов не содержат символ новой строки:

 grep -L '[[:print:]]' -- * | while IFS= read -r filename; do if [ -f "$filename" ] && [ -s "$filename" ]; then rm "$filename" fi done 

или эквивалентно (обратите внимание, что это также удаляет пустые файлы)

 set +f; IFS=' ' # split at newlines, turn off globbing rm -- $(set -f; grep -L '[[:print:]]' -- *) set -f; unset IFS 

Обратите внимание, что приведенные выше команды выдадут сообщения об ошибках, если в текущем каталоге есть подкаталоги (потому что вы будете называть rm в каталоге – не вызывайте rm -r !). В zsh вы можете использовать *(.L+0) вместо * только для соответствия регулярным непустым файлам, и вам не нужно беспокоиться о специальных символах в именах файлов (кроме строк новой строки):

 IFS=$'\n' rm -- $(grep -L '[[:print:]]' -- *(.)) unset IFS 

С помощью только инструментов POSIX grep -l '[[:print:]]' -- * показывает файлы, которые вы хотите сохранить (кроме пустых файлов).

Или вы можете перебирать файлы; это яснее и не вызывает проблем со специальными символами (но пропускает файлы точек), но теоретически (но, вероятно, не измеримо) медленнее.

 for x in *; do if [ -f "$x" ] && [ -s "$x" ] && ! grep -q '[[:print:]]' <"$x"; then rm -- "$x" fi done 

Лучше всего использовать file . Попробуй это:

 find . -type f -exec file {} + | grep ": data" 

Теперь это не будет ловить файлы, которые случайно имеют правильное магическое число с самого начала, но вполне вероятно, что большинство других методов будут пропускать их в любом случае.

Другие способы поиска этих файлов:

  • Последнее изменение времени: find -mmin 5 = 5 мин назад
  • Размер, не обязательно нуль: find -size -4k = менее 4096 байт