Коли я хочу шукати деяке вміст у цілому дереві, я використовую
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'
греп 'дослідження'
{}
у знайденому імені файлу
'+'
використовувати одну команду для всіх імен файлів, а не один раз для імені файлу.
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, як інструменти няні мене (якщо вони не надають дивну магію, яку вони називають "AI"). (-;
Як зазначено вище -r
або -R
(залежно від бажаної обробки символьної лінії), це швидкий варіант.
Однак -d <action>
може бути корисним часом.
Приємно в тому, що -d
це команда пропуск, яка замовчує "grep: directory_name: Є каталог", коли ви просто хочете сканувати поточний рівень.
$ 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 "primary" `find . | grep cpp$` | grep -v "ignoreThis" | grep -i "caseInsensitiveGrep"