Фильтровать файлы, сгенерированные `find`, с помощью обработанного вывода команды` file`

Я пишу быстрый инструмент для проверки содержимого папки node.js node_modules или python virtualenv для собственных зависимостей. В качестве быстрого первого приближения к этому я написал следующую команду.

 find . | xargs file | awk '/C source/ {print $1} /ELF/ {print $1}' 

Я в порядке с ложными срабатываниями, но не ложными негативами (например, файлы, буквально содержащие строку ELF или C source могут быть помечены подозрительными.), Но этот скрипт также потенциально ломается на длинных именах файлов (поскольку xargs будет их разделять) и имена файлов, содержащие пробелы (потому что awk будет разделяться на пробелы) и имена файлов, содержащие новые строки (потому что find использует новые строки для разделения путей).

Есть ли способ фильтровать пути, сгенерированные find , если вы видите, что вывод file {} (возможно, с некоторыми дополнительными параметрами для удаления пути целиком из вывода file ) соответствует определенному регулярному выражению?

2 Solutions collect form web for “Фильтровать файлы, сгенерированные `find`, с помощью обработанного вывода команды` file`”

Ключевым фактором в достижении find просвещения является:):

бизнес find – это оценка выражений – не поиск файлов. Да, find конечно, находит файлы; но это действительно просто побочный эффект.

–Unix Электроинструменты

Существует альтернативный подход к этому вопросу, о котором стоит знать (как описано в Unix Power Tools, в разделе «Использование -exec для создания пользовательских тестов» ):

 find . -type f -exec sh -c 'file -b "$1" | grep -iqE "^ELF|^C source"' sh {} \; -print 

Стоит знать об этом методе фильтрации, поскольку его можно использовать для многих других вещей, чем просто распечатать имя файла; просто измените оператор -print на любой другой оператор, который вам нравится (в том числе другой -exec оператор) и сделайте то, что вам нравится.


Существует недостаток производительности для этой команды (которая также присутствует в другом ответе ), которая заключается в том, что, поскольку мы используем \; и не + , мы создаем оболочку для каждого отдельного файла. Использование + для одновременного передачи нескольких файлов команде sh и обработки их циклом for дает заметное преимущество в производительности:

 find . -exec sh -c 'for f do file -b "$f" | grep -qE "^ELF|^C source" && printf %s\\n "$f"; done' sh {} + 

Вы можете увидеть сравнение для себя, выполнив обе следующие команды и сравнив вывод time :

 time find . -exec sh -c 'for f do file -b "$f" | grep -qE "^ELF|^C source" && printf %s\\n "$f"; done' sh {} + time find . -exec sh -c 'file -b "$1" | grep -qE "^ELF|^C source" && printf %s\\n "$1"' sh {} \; 

Реальная точка, однако, заключается в следующем:

Никогда не запускайте оболочку for цикла в списке файлов, которые выводятся из find . Вместо этого запустите действие, которое необходимо выполнить для каждого файла непосредственно внутри find , используя оператор -exec или вставьте оболочку for цикла внутри команды find и сделайте это таким образом.

Некоторые дополнительные причины:

  • Почему мой сценарий оболочки задыхается от пробелов или других специальных символов?
  • Почему использование цикла оболочки для обработки текста считается плохой практикой?

Проще всего выполнить небольшой скрипт для каждого файла, который проверяет вывод в кратком режиме file и печатает путь, если выход file соответствует ELF или C source , путь передается как $0 .

 find . -type f -exec sh -c \ 'file -b "$0" | grep -q "^ELF\|^C source" && printf %s\\n "$0"' {} \; 

Это решение имеет следующие преимущества перед оригиналом

-type f отфильтровывает каталоги сразу вместо того, чтобы полагаться на вывод file

Передача аргумента как {} позволяет избежать проблем, связанных с пробелом или новой строкой в ​​имени файла.

  • проблема с цитированием вывода ls
  • Найти файл, имя которого содержит заданные подстроки одновременно
  • Как вычислить общий размер файла, который вы искали с помощью команды «Найти»
  • Есть ли способ найти файл в обратном рекурсивном поиске?
  • Сценарий очистки с помощью find и anacron
  • Как использовать команду find для перечисления общедоступных записываемых файлов в каталог, не переходя в какие-либо подкаталоги?
  • Как переименовать несколько файлов, используя find
  • проблема с find (shell script)
  • найти . . * -тип f -print0 | xargs -0 sudo chmod 664; не работает
  • Поиск файлов на сервере Unix и сортировка по размеру
  • Найти каталоги с определенным именем
  • Interesting Posts

    Ограничьте пропускную способность отдельных HTTP-запросов, не ограничивая общую пропускную способность

    Цветовая схема Vim не всегда работает

    iptables-persistent блокировка любых исходящих подключений

    Как я могу полностью удалить элемент из массива?

    Лучшие загрузочные диски usb для Linux?

    btrfs – снимок родительского подвыбора исключает дочерние подвыборы?

    Удалить неизвестный символ юникода из textfiles – sed, другие методы bash / shell

    Как запомнить пароль ssh с помощью lsyncd?

    Справка по установке / настройке Samba 2.2.3a на Ubuntu 14.04

    Как отслеживать трафик при туннелировании SSH?

    Отключение срока действия пароля для автоматического входа в систему Пользователь Linux

    Является ли ядро ​​удалять записи в / dev на initramfs?

    Я не могу подключиться к моему маршрутизатору, когда меняю адрес wlan0 mac на Ubuntu 14.04

    Как я могу создать DEB из установленного пакета?

    CentOS 6.4: невозможно монтировать диск, не нравится UDF

    Linux и Unix - лучшая ОС в мире.