Как передать список файлов в grep

98

Я использую findи получаю список файлов, которые я хочу grepпросмотреть. Как мне передать этот список grep?

Arcabard
источник

Ответы:

116

Что ж, общий случай, который работает с любой командой, которая пишет в 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' {} \+
Михаил Мрозек
источник
1
Следует отметить, что первые две формы не работают с именами файлов, содержащими пробелы.
энзотиб
1
Я предпочитаю find ... -type f -print0 | xargs -r0 grep 'search' /dev/null. QED. Хотя -exec +это очень эффективно, его нет на всех версиях find.
Arcege
К сожалению, я не могу проверить вас правильно 3 раза.
Arcabard
3
Я предлагаю использовать -exec, а не xargs. Если вы используете -execin find, он создаст только одну оболочку для поиска содержимого. Если вы используете xargs, он создаст две оболочки: одну для findдругой, а другую для xargs.
2
экспериментально я обнаружил, что $ find … -exec grep 'search' {} \+форма намного быстрее.
gogoud
9

В некоторых версиях 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опцию для достижения того же эффекта).

find . -type f -name '*.o' -prune -o -exec grep 'needle' /dev/null {} +
grep -r --exclude='*.o' 'needle' .
жилль
источник
2
GNU grepимеет -Hвозможность всегда печатать имя файла.
энзотиб