Когда я хочу найти какое-то содержимое во всем дереве, я использую
find . -type f -print0 | xargs -0 grep <search_string>
Есть ли лучший способ сделать это с точки зрения производительности или краткости?
Когда я хочу найти какое-то содержимое во всем дереве, я использую
find . -type f -print0 | xargs -0 grep <search_string>
Есть ли лучший способ сделать это с точки зрения производительности или краткости?
Ответы:
Проверьте, grepподдерживает ли ваш -rвариант поддержки (для рекурса ):
grep -r <search_string> .
--exclude-dirпроизводительности выступления и у нас есть победитель!
grepна последних дистрибутивах FreeBSD и Linux это поддерживается. А почему --exclude-dir? Разве вы не просили обыскать целое дерево ?
--exclude-dirна самом деле удобно в моем случае использования (потому что части поддерева большие, но бесполезные), и я спросил о производительности ... но вы правы, в этом нет необходимости.
--exclude-dirявляется эксклюзивным для GNU grep. (-:
Субоптимальный ответ: вместо того, чтобы передать результаты findв grep, вы можете просто запустить
find . -type f -exec grep 'research' {} '+'
и вуаля, одна команда вместо двух!
объяснение:
find . -type f
найти все обычные файлы в.
-exec grep 'research'
grep 'исследование'
{}
в найденном имени файла
'+'
используйте одну команду для всех имен файлов, а не один раз для каждого имени файла.
Nb: с ';'этим было бы один раз за имя файла.
Помимо этого, если вы используете это для обработки исходного кода, вы можете посмотреть ack, что сделано для легкого поиска битов кода.
Редактировать :
Вы можете немного расширить это исследование. Во-первых, вы можете использовать -name ''переключатель findдля поиска файлов с указанным шаблоном именования.
Например :
только файлы, которые соответствуют журналам: -name '*.log'
только файлы, которые соответствуют заголовкам c, но вы не можете использовать прописные или строчные буквы для своих расширений файлов: -iname *.c
Nb: как для grepи ack, -iпереключатель означает, что в этом случае не учитывается регистр.
В этом случае grep будет отображаться без цвета и без номеров строк.
Вы можете изменить это с --colorи -nпереключатели (цвет и линий чисел в файлах , соответственно).
В конце концов, вы можете получить что-то вроде:
find . -name '*.log' -type f -exec grep --color -n 'pattern' {} '+'
например
$ find . -name '*.c' -type f -exec grep -n 'hello' {} '+'
./test2/target.c:1:hello
-name '*.log'это быстрее.
Если вы хотите перейти в подкаталоги:
grep -R 'pattern' .
Эта -Rопция не является стандартной, но поддерживается большинством распространенных grepреализаций.
-rвместо -Rпропуска символических ссылок, когда дело касается GNU grep
grepреализации GNU ловят рекурсии, я думаю. В противном случае это зависит от того, что вы подразумеваете под «деревом».
grepдолжен делать инструмент, подобный этому. Если у пользователя есть символьные циклы ссылок в его структуре каталогов, ну, это проблема пользователя :-)
/sys/devices/cpu/subsystem/devices/cpu/subsystem/devices/cpu/...(-XI, как инструменты, присматривающие за мной (если они не обеспечивают странную магию, которую они называют «ИИ»). (-;
Как отмечено выше -rили -R(в зависимости от желаемой обработки символической ссылки), это быстрый вариант.
Однако -d <action>может быть полезным в разы.
Приятной особенностью -dявляется команда skip, которая отключает "grep: directory_name: Is a directory", когда вы просто хотите просканировать текущий уровень.
$ grep foo *
grep: q2: Is a directory
grep: rt: Is a directory
$ grep -d skip foo *
$
и конечно:
$ grep -d recurse foo *
(list of results that don't exist because the word foo isn't in our source code
and I wouldn't publish it anyway).
$
Эта -d skipопция ДЕЙСТВИТЕЛЬНО удобна внутри другого скрипта, поэтому вам не нужно это делать 2> /dev/null. :)
Если вы имеете дело с большим количеством файлов, grep работает быстрее, если вы удаляете файлы, которые необходимо найти, вместо того, чтобы подбирать все файлы в подпапках.
Я использую этот формат иногда:
grep "primary" `find . | grep cpp$`
Найти все файлы в подпапках .этого конца вcpp . Затем grep эти файлы для "основного".
Если вы хотите, вы можете продолжать передавать эти результаты в дальнейшие вызовы grep:
grep "primary" `find . | grep cpp$` | grep -v "ignoreThis" | grep -i "caseInsensitiveGrep"