Я использую find
и получаю список файлов, которые я хочу grep
просмотреть. Как мне передать этот список grep
?
Что ж, общий случай, который работает с любой командой, которая пишет в stdout, - это использование xargs
, которое позволит вам присоединить любое количество аргументов командной строки к концу команды:
$ find … | xargs grep 'search'
Или встроить команду в вашу grep
строку с помощью обратных кавычек или $()
, которая запустит команду и подставит ее вывод:
$ grep 'search' $(find …)
Обратите внимание, что эти команды не работают, если имена файлов содержат пробелы или некоторые другие «странные символы» ( \'"
для xargs, \[*?
для $(find …)
).
Однако в конкретном случае find
возможность выполнения программы по заданным аргументам является встроенной:
$ find … -exec grep 'search' {} \;
Все, что находится между -exec
и ;
является командой для выполнения; {}
заменяется найденным именем файла find
. Это будет выполняться отдельно grep
для каждого файла; поскольку grep
может занять много имен файлов и искать их все, вы можете изменить , ;
чтобы +
сказать найти , чтобы передать все совпадающие имена файлов grep
сразу:
$ find … -exec grep 'search' {} \+
find ... -type f -print0 | xargs -r0 grep 'search' /dev/null
. QED. Хотя-exec +
это очень эффективно, его нет на всех версиях find.-exec
, а неxargs
. Если вы используете-exec
infind
, он создаст только одну оболочку для поиска содержимого. Если вы используетеxargs
, он создаст две оболочки: одну дляfind
другой, а другую дляxargs
.$ find … -exec grep 'search' {} \+
форма намного быстрее.В некоторых версиях
grep
(например, в не встроенных Linux, BSD или Mac OS X) есть-r
возможность сделать рекурсивный поиск. В OpenBSD используйте-R
(и нет,--exclude
как в примере ниже). Это охватывает простые комбинацииfind
сgrep
.Если ваша реализация не имеет
-R
флага, или если вам нужны более подходящие критерии соответствия файлов, вы можете использовать-exec
основной из них,find
чтобы заставить его выполнятьсяgrep
. Несколько более старыхfind
реализаций не поддерживают-exec
...+
; в этих системах используйте;
вместо+
(это будет вызыватьсяgrep
один раз для каждого файла, так что это будет медленнее, но в противном случае результат будет таким же). Обратите внимание на/dev/null
хитрость, позволяющуюgrep
отображать имя файла, даже если оно вызывается в одном файле (GNU grep и FreeBSD / NetBSD / OSX grep имеют-H
опцию для достижения того же эффекта).источник
GNU grep
имеет-H
возможность всегда печатать имя файла.