Kiedy chcę przeszukać całe drzewo w poszukiwaniu jakiejś zawartości, używam
find . -type f -print0 | xargs -0 grep <search_string>
Czy istnieje lepszy sposób na zrobienie tego pod względem wydajności lub zwięzłości?
Kiedy chcę przeszukać całe drzewo w poszukiwaniu jakiejś zawartości, używam
find . -type f -print0 | xargs -0 grep <search_string>
Czy istnieje lepszy sposób na zrobienie tego pod względem wydajności lub zwięzłości?
Odpowiedzi:
Sprawdź, czy opcja grep
wsparcia -r
(w przypadku ponownego wystąpienia ):
grep -r <search_string> .
--exclude-dir
wydajności, a my mamy zwycięzcę!
grep
w najnowszych dystrybucjach FreeBSD i Linux go obsługuje. A dlaczego --exclude-dir
? Nie prosiłeś o przeszukanie całego drzewa ?
--exclude-dir
jest w rzeczywistości przydatny w moim przypadku użycia (ponieważ części poddrzewa są duże, ale bezużyteczne) i zapytałem o wydajność ... ale masz rację, nie jest to konieczne.
--exclude-dir
jest wyłączne dla GNU grep
. (-:
Nieoptymalna odpowiedź: Zamiast przesyłać dane wyjściowe find
do grep
, możesz po prostu uruchomić
find . -type f -exec grep 'research' {} '+'
i voila, jedno polecenie zamiast dwóch!
wyjaśnienie:
find . -type f
znajdź wszystkie zwykłe pliki.
-exec grep 'research'
grep „research”
{}
w znalezionej nazwie pliku
'+'
użyj jednego polecenia dla wszystkich nazw plików, a nie raz dla nazwy pliku.
Uwaga: z ';'
tym byłby raz na nazwę pliku.
Poza tym, jeśli używasz go do przetwarzania kodu źródłowego, możesz zajrzeć do niego ack
, co jest przeznaczone do łatwego wyszukiwania bitów kodu.
Edytować :
Możesz trochę rozszerzyć te badania. Po pierwsze, możesz użyć -name ''
przełącznika, find
aby wyszukać pliki z określonym wzorcem nazewnictwa.
Na przykład :
tylko pliki odpowiadające dziennikom: -name '*.log'
tylko pliki odpowiadające nagłówkom c, ale nie możesz trzymać się wielkich lub małych liter dla rozszerzeń plików: -iname *.c
Nb: jak dla grep
i ack
, -i
przełącznik oznacza w tym przypadku rozróżnianie wielkości liter.
W takim przypadku grep wyświetli się bez koloru i bez numerów linii.
Można to zmienić z --color
i -n
przełączniki (numery kolorów i linii w plikach odpowiednio).
Na koniec możesz mieć coś takiego:
find . -name '*.log' -type f -exec grep --color -n 'pattern' {} '+'
na przykład
$ find . -name '*.c' -type f -exec grep -n 'hello' {} '+'
./test2/target.c:1:hello
-name '*.log'
To jest szybsze.
Jeśli chcesz przekierować do podkatalogów:
grep -R 'pattern' .
Ta -R
opcja nie jest opcją standardową, ale jest obsługiwana przez większość popularnych grep
implementacji.
-r
zamiast -R
pomijać dowiązania symboliczne, gdy dotyczy GNU grep
grep
implementacje GNU wychwytują rekurencje, myślę. W przeciwnym razie zależy to od tego, co rozumiesz przez „drzewo”.
grep
powinno zrobić narzędzie . Jeśli użytkownik ma symboliczne pętle linków w swojej strukturze katalogów, to jest problem użytkownika :-)
/sys/devices/cpu/subsystem/devices/cpu/subsystem/devices/cpu/...
(-XI jak narzędzia opiekujące się mną (chyba że zapewniają dziwną magię, nazywają „AI”). (-;
Jak wspomniano powyżej -r
lub -R
(w zależności od pożądanej obsługi dowiązań symbolicznych) jest szybką opcją.
-d <action>
Czasami jednak może się przydać.
Przyjemną rzeczą -d
jest komenda skip, która ucisza „grep: nazwa_katalogu: Jest katalogiem”, gdy chcesz tylko przeskanować bieżący poziom.
$ grep foo *
grep: q2: Is a directory
grep: rt: Is a directory
$ grep -d skip foo *
$
i oczywiście:
$ 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
Opcja jest naprawdę przydatne wewnątrz innego skryptu, dzięki czemu nie trzeba 2> /dev/null
. :)
Jeśli masz do czynienia z wieloma plikami, grep działa szybciej, jeśli przycinasz pliki, które musi przeszukać, zamiast grepowania wszystkich plików w podfolderach.
Czasami używam tego formatu:
grep "primary" `find . | grep cpp$`
Znajdź wszystkie pliki w podfolderach .
tego końca w cpp
. Następnie grep te pliki dla „podstawowego”.
Jeśli chcesz, możesz przesyłać dalej te wyniki do kolejnych wywołań grep:
grep "primary" `find . | grep cpp$` | grep -v "ignoreThis" | grep -i "caseInsensitiveGrep"