Поиск подстроки в файлах в подкаталогах с помощью одной встроенной команды?

10

В Windows, если бы я хотел найти строку во всех файлах во всех подкаталогах, я бы сделал что-то вроде

findstr /C:"the string" /S *.h

Тем не менее, в Linux (скажем, Ubuntu) я не нашел другого пути, кроме какой-либо конвейерной команды, включающей find, xargsи grep(пример на этой странице: Как я могу рекурсивно выполнять поиск в подкаталогах? ). Однако у меня другой вопрос: есть ли какая-то одна встроенная команда, которая работает через это волшебство, без необходимости писать мой сценарий оболочки?

Гвидо Доменичи
источник

Ответы:

19

GNU grep позволяет выполнять рекурсивный поиск по подкаталогам:

grep -r --include='*.h' 'the string' .
шутник
источник
Я попробовал эту точную командную строку в Ubuntu, но получил «grep: invalid option -« M »», хотя нигде не вижу ни одной буквы «M» ... озадачивает
Guido Domenici
@Guido отлично работает здесь
phunehehe
В предлагаемом редакторе TomasG рекомендует изменить последний *на '*': «Необходимо использовать последний подстановочный знак во избежание ошибок, когда некоторые имена файлов начинаются с -»
Майкл Мрозек
По странному стечению обстоятельств, теперь это работает и для меня, как указано в исходном ответе. Спасибо!
Гвидо Доменичи
1
@Guido: Ваша проблема могла быть связана с файлом в текущем каталоге -Msomethingили с GREP_OPTIONSнастройкой.
Жиль "ТАК - перестань быть злым"
2

grep -r searchpattern /path/to/start/in

Где /path/to/start/in/может быть просто " ." для текущего каталога.

mattdm
источник
1

Нет, find -name \*.h -print0 | xargs -0 grep -l 'the regex'это волшебство, какое только возможно.

Гленн Джекман
источник
GNU grep имеет общие случаи, встроенные в его -rопцию. Нет необходимости в тяжелой артиллерии.
Жиль "ТАК - перестань быть злым"
3
xargsдобавляет только шум. Использованиеfind -name \*.h -execdir grep -l 'the regex {} +
пользователь неизвестен
0

есть ли одна встроенная команда, которая работает через эту магию ...?

Чтобы быть педантичным, нет, вы не можете предполагать, что такая команда существует .

Существует множество различных реализаций Unix, и у каждой есть свои особенности. POSIX, общий знаменатель (и самый близкий к стандарту в Unices) такой параметр не указывает дляgrep .

Как упоминалось в других ответах, реализация GNU grepимеет нестандартную опцию, которая делает то, что вы хотите. Хотя эта конкретная реализация может быть распространена в системах Linux, вы не можете предполагать ее доступность в любом Unix, даже в некоторых системах Linux.

Наконец, я должен отметить, что философия Unix заключается в том, чтобы отдавать предпочтение комбинации нескольких примитивных программ, а не использованию одного большого монолитного исполняемого файла, пытающегося сделать все сразу.

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

rahmu
источник
0

Чтобы найти строку из данного каталога, используйте команду ниже

find <fullDirectoryPath> -name '*' -exec grep -l '<StringToFind>' {} \;

Например:

find /apps_bev/apps/xfer/export/02210 -name '*' -exec grep -l '38221000001032' {} \;
Yogesh
источник
1
grepможет принимать более одного файла в качестве аргументов, поэтому вы должны использовать +вместо того, \;чтобы избежать запуска одного grepвызова на файл, что довольно неэффективно.
Стефан
1
Обратите внимание, что это -name '*'относится только к файлам, чье имя является допустимым текстом в текущей локали ( findпо крайней мере, в некоторых реализациях), но другие компоненты каталога могут по-прежнему содержать последовательности байтов, которые не образуют допустимых символов. Если вы намерены -name '*'сделать так, чтобы вывод был корректным текстом (пропуская файлы с неправильными именами), вы бы предпочли использовать find ... ! -name '*' -prune -o -exec grep ... {} +, что также не позволит findспускаться в каталоги с неправильными именами.
Стефан