Строка поиска: найди и найди - PullRequest
5 голосов
/ 15 ноября 2011

Должен быть лучший / более короткий способ сделать это:

# Find files that contain <string-to-find> in current directory
#   (including sub directories) 
$ find . | xargs grep <string-to-find>

Кроме того, для поиска только, например, HTML-файлы:

 # find . | grep html$ | xargs grep <string-to-find>

Заранее спасибо!

Ответы [ 4 ]

18 голосов
/ 15 ноября 2011
find . -name \*.html

или, если вы хотите найти файлы с именами, совпадающими с регулярным выражением:

find . -regex filename-regex.\*\.html 

или, если вы хотите найти регулярное выражение в файлах с именами, совпадающими с регулярным выражением

find . -regex filename-regex.\*\.html -exec grep -H string-to-find {} \;

Аргумент grep -H выводит имя файла, если оно представляет интерес.Если нет, вы можете безопасно удалить его и просто использовать grep.Это будет указывать find на выполнение grep string-to-find filename для каждого найденного им имени файла, что исключает возможность слишком длинного списка аргументов и необходимость завершения выполнения find до того, как он сможет передать свои результаты в xargs.


В качестве примеров:

find . | xargs grep <string-to-find>

можно заменить на

find . -exec grep -H string-to-find {} \;

и

find . | grep html$ | xargs grep <string-to-find>

можнозаменено на

find . -name \*.html -exec grep -H string-to-find {} \;
3 голосов
/ 15 ноября 2011

Не уверен, что вы имеете в виду под лучше, моя первая мысль была что-то вроде этого:

grep <string-to-find> $(find -regex .*\.html)

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

Единственное улучшение, которое я вижу, тоже ваше предложение

find -regex .*\.html | xargs grep <string-to-find>

Таким образом find выполняет всю фильтрацию, и вы все равно сохраняете конвейерную обработку

2 голосов
/ 19 ноября 2011

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

Помимо других приведенных ответов, я также предлагаю следующую конструкцию: find . -type f -name "*.html" -print|xargs -I FILENAME grep "< string-to-find>" FILENAME Еще лучше, если в именах файлов есть пробелы, вы можете либо заключить в кавычки "FILENAME", либо передать результат с нулевым символом в конце (вместо символа новой строки) от find до xargs, а затем получить xargs stripсами по себе: find . -type f -name "*.html" -print0|xargs -0 -I FILENAME grep "< string-to-find>" FILENAME here --^ and --^

Здесь имя FILENAME на самом деле может быть любым, но оно должно соответствовать обоим find . -type f -name "*.html" -print0|xargs -0 -I FILENAME grep "< string-to-find>" FILENAME here --^ and --^ Вот так: find . -type f -name "*.html" -print0|xargs -0 -I GRRRR grep "< string-to-find>" GRRR this --^ this --^

По сути, это делаетто же самое, что и {}, используемый в самом операторе find для указания "строки текста, которую он вернул".В противном случае, xargs просто привязывает результаты find к КОНЦУ всех остальных команд, которые вы ему даете (что не очень помогает, если вы хотите grep искать внутри файла, который обычно задается последний в командной строке).

0 голосов
/ 15 ноября 2011

Уверен, это единственный способ. Вам придется пересмотреть каждую папку, затем каждую подпапку и проверить каждый файл.
Единственное, о чем я могу думать, это то, что серверный код бросает структуру каталогов и файлов в запрос LINQ, а затем вы можете выполнить SQL-подобный запрос. но затем сервер в конечном итоге сделает то же самое.

...