Коли я хочу шукати деяке вміст у цілому дереві, я використовую
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"