Когда я хочу найти какое-то содержимое во всем дереве, я использую
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"