Unix 'find' + 'grep' синтаксис против awk - PullRequest
3 голосов
/ 22 июня 2009

Я использовал эту строку, чтобы найти фразу «B206» в файлах в каталоге, в котором я находился, и во всех его подкаталогах.

find . -exec grep -s "B206" '{}' \; -print 

Вылетает, когда он пытается прочитать определенные файлы и фактически меняет строку заголовка в замазке на кучу странных символов

Например, он постоянно падает, когда попадает в jpg-файл, который находится в подкаталоге. Строка заголовка изменится, и на экране появится:

ÐF»*rkNQeË+Z׳kU£~MÞçÄZ½ªéúýØâÑn¡[U+Þ4ªÒ9/ê£<ú¯4}[IÓ­îÃ¥K»G%ݳ¢

Вынуждая меня снова нажать Ctrl + C, а затем выйти.

Есть ли способ добавить в эту строку код, исключающий файлы jpg? Еще лучше, кусок кода, где я могу добавить список расширений, чтобы исключить?


РЕДАКТИРОВАТЬ:
-не & -Я у меня не работает
Я нашел этот похожий вопрос , также связанный с моим

Ответы [ 12 ]

8 голосов
/ 22 июня 2009

Нет смысла использовать find: grep поставляется с рекурсивной опцией, -r. Чтобы просто получить список имен файлов с совпадениями (в отличие от списка всех совпадающих строк во всех файлах), вы можете использовать опцию -l. Если вы хотите полностью игнорировать все двоичные файлы, вы можете использовать опцию --binary-files=without-match. Если вы хотите игнорировать только файлы с определенным расширением, вы можете использовать опцию --exclude, например, --exclude=*.{jpg,jpeg}, чтобы игнорировать все файлы, заканчивающиеся на .jpg или .jpeg. Таким образом, вы должны быть в состоянии получить то, что вы хотите с этим:

grep -r -l --binary-files=without-match .

Теперь вы упомянули в одном из ваших комментариев, что ваша версия grep не имеет параметров -r или -l. Это прискорбно, и я рекомендую получить более свежую версию grep (предпочтительно разновидности GNU).

Еще одно замечание: если вы используете find -exec, вы должны использовать + для завершения команды вместо точки с запятой, например ::

find . -exec grep options '{}' '+'

Используя +, find отключит только один процесс и передаст все совпадающие имена файлов в качестве аргументов командной строки одному экземпляру grep. Пока у вас нет миллиона подходящих файлов (что создаст командную строку гораздо дольше, чем может обработать оболочка), это будет намного, намного быстрее. Если вместо этого вы используете точку с запятой, find разветвляет новый процесс для каждого соответствующего файла, что очень медленно для очень большого количества файлов.

3 голосов
/ 22 июня 2009

Если ваша среда не может выполнять какие-либо действия, возможно, ваш awk сможет это сделать:

find . | awk '!/((\.jpeg)|(\.jpg)|(\.png))$/ {print $0;}' | xargs grep "B206"
3 голосов
/ 22 июня 2009

Просто цитата, вам не нужно закрывать терминал, вы можете использовать команду reset для восстановления режима вывода терминала.

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

find -print | grep -v '\(\.jpg\|\.bmp\)$' | xargs grep "B206"
3 голосов
/ 22 июня 2009

Вы можете использовать переключатель -I grep:

Process  a  binary  file as if it did not contain matching data;
this is equivalent to the --binary-files=without-match option.

Короче говоря, grep будет просто предполагать, что файл не соответствует, что будет препятствовать выводу двоичных данных.

2 голосов
/ 22 июня 2009

Учитывая недавний lovefest более ack , я удивлен, что никто еще не упомянул об этом.

Вы можете настраивать типы по расширению, чтобы вы «grep» только те файлы, которые вы хотите. Или вы можете просто использовать - nobinary , учитывая проблему, с которой вы столкнулись.

2 голосов
/ 22 июня 2009

Я попробовал команду Эрика, но получил ошибку об отсутствии предиката -grep. Возможно, моя версия find слишком старая.

Это сработало для меня:

find . -type f -a -not -name \*.jpg -exec grep "B206" {} \;
2 голосов
/ 22 июня 2009
find . -type f -a -not -name \*.jpg -exec grep -li "string" "{}" \;

Этот пример взят из Mac OSX 10.5, вам необходимо проверить страницу поиска для вашей среды, поскольку существует некоторое расхождение между GNU find и реализациями других поставщиков. Проверка Solaris (ради интереса, целевая ОС никогда не указывалась):

find . -type f -a ! -name \*.jpg -exec grep -li "string" "{}" \;

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

В зависимости от вашей оболочки, вам может понадобиться избежать взрыва (!), Чтобы это работало так, как рекламируется.

1 голос
/ 22 июня 2009

Я думаю, что проблема в том, что когда вы выполняете grep двоичного файла, он выводит двоичные данные. Эти двоичные данные как-то интерпретируются в вашей оболочке.

Я бы предложил попробовать использовать команду "strings", которая гарантирует, что ваш вывод сначала только текстовый, а затем grep при выводе "strings".

1 голос
/ 22 июня 2009

Чтобы использовать grep с find, мой синтаксис:

find . -name "*" -print | xargs grep B206

Все параметры фильтрации файлов, двоичные и все, затем результаты передаются в качестве аргументов команде grep.

1 голос
/ 22 июня 2009
grep -r --exclude=*.jpg B206 .

Извините, из другого комментария:

Только GNU grep поставляется с -r (рекурсивно), истинная UNIX grep - нет. Вы должны либо установить GNU grep, либо использовать его с find. - конечная остановка

...