Nie jestem pewny:
grep -r -i 'the brown dog' /*
to naprawdę to, co miałeś na myśli. Oznaczałoby to rekurencyjnie grep we wszystkich nie ukrytych plikach i katalogach w /
(ale nadal zaglądanie do ukrytych plików i katalogów wewnątrz nich).
Zakładając, że miałeś na myśli:
grep -r -i 'the brown dog' /
Kilka rzeczy do zapamiętania:
- Nie wszystkie
grep
implementacje obsługują -r
. A wśród tych, które się tak zachowują, zachowania się różnią: niektóre podążają za dowiązaniami symbolicznymi do katalogów podczas przechodzenia przez drzewo katalogów (co oznacza, że możesz skończyć przeglądać kilka razy w tym samym pliku lub nawet działać w nieskończonych pętlach), niektóre nie. Niektóre zaglądają do plików urządzeń ( /dev/zero
na przykład zajmie to trochę czasu ) lub potoków lub plików binarnych ... niektóre nie.
- Jest skuteczny, ponieważ
grep
zaczyna przeszukiwać pliki, gdy tylko je odkryje. Ale gdy szuka w pliku, nie szuka już więcej plików do przeszukania (co w większości przypadków jest prawdopodobnie równie dobre)
Twój:
find / -type f -exec grep -i 'the brown dog' {} \;
(usunięto to, -r
co nie miało sensu tutaj) jest strasznie nieefektywne, ponieważ uruchamiasz jeden grep
na plik. ;
powinien być używany tylko dla poleceń, które akceptują tylko jeden argument. Ponadto tutaj, ponieważ grep
wygląda tylko w jednym pliku, nie wydrukuje nazwy pliku, więc nie będziesz wiedział, gdzie są dopasowania.
Nie przeglądasz plików urządzeń, potoków, dowiązań symbolicznych ..., nie podążasz za dowiązaniami symbolicznymi, ale nadal potencjalnie zaglądasz do takich rzeczy jak /proc/mem
.
find / -type f -exec grep -i 'the brown dog' {} +
byłoby znacznie lepiej, ponieważ grep
uruchomiono by jak najmniej poleceń. Otrzymasz nazwę pliku, chyba że ostatnie uruchomienie zawiera tylko jeden plik. W tym celu lepiej użyć:
find / -type f -exec grep -i 'the brown dog' /dev/null {} +
lub z GNU grep
:
find / -type f -exec grep -Hi 'the brown dog' {} +
Pamiętaj, że grep
nie zostanie uruchomiony, dopóki find
nie znajdzie wystarczającej liczby plików do przeżuwania, więc wystąpi pewne początkowe opóźnienie. I find
nie będzie kontynuował wyszukiwania kolejnych plików, dopóki poprzednie grep
nie powróci. Przydzielanie i przekazywanie dużej listy plików ma pewien (prawdopodobnie nieistotny) wpływ, więc w sumie prawdopodobnie będzie mniej wydajne niż to, grep -r
że nie podąża za dowiązaniem symbolicznym ani nie przegląda urządzeń.
Za pomocą narzędzi GNU:
find / -type f -print0 | xargs -r0 grep -Hi 'the brown dog'
Jak wyżej, grep
uruchomionych find
zostanie jak najmniej instancji, ale będzie ona nadal szukała więcej plików, podczas gdy pierwsze grep
wywołanie zajrzy do pierwszej partii. To może, ale nie musi być zaletą. Na przykład dane przechowywane na obrotowych dyskach twardych find
i grep
uzyskiwanie dostępu do danych przechowywanych w różnych miejscach na dysku spowolnią przepustowość dysku, powodując ciągłe ruchy głowicy dysku. W konfiguracji RAID (gdzie find
i grep
może uzyskiwać dostęp do różnych dysków) lub na dyskach SSD może to mieć pozytywny wpływ.
W konfiguracji RAID, bieganie kilka jednoczesnych grep
wywołania może również poprawić rzeczy. Nadal z narzędziami GNU na macierzy RAID1 z 3 dyskami,
find / -type f -print0 | xargs -r0 -P2 grep -Hi 'the brown dog'
może znacznie zwiększyć wydajność. Zauważ jednak, że drugi grep
zostanie uruchomiony dopiero po znalezieniu wystarczającej liczby plików do wypełnienia pierwszego grep
polecenia. Możesz dodać -n
opcję xargs
, aby stało się to wcześniej (i przekazać mniej plików na jedno grep
wywołanie).
Zauważ też, że jeśli przekierowujesz xargs
dane wyjściowe na cokolwiek innego niż urządzenie końcowe, greps
s zacznie buforować swoje dane wyjściowe, co oznacza, że dane wyjściowe tych grep
prawdopodobnie zostaną nieprawidłowo przeplecione. Będziesz musiał użyć na nich stdbuf -oL
(jeśli jest dostępny, jak na GNU lub FreeBSD), aby obejść ten problem (nadal możesz mieć problemy z bardzo długimi liniami (zazwyczaj> 4KiB)) lub poproś każde z nich o zapisanie ich wyników w osobnym pliku i połączenie ich. wszystko w końcu.
Tutaj ciąg, którego szukasz, jest naprawiony (nie jest wyrażeniem regularnym), więc użycie tej -F
opcji może mieć znaczenie (mało prawdopodobne, ponieważ grep
implementacje wiedzą, jak to zoptymalizować).
Inną rzeczą, która może mieć dużą różnicę, jest ustawienie języka na C, jeśli jesteś w ustawieniu wielobajtowym:
find / -type f -print0 | LC_ALL=C xargs -r0 -P2 grep -Hi 'the brown dog'
Aby uniknąć zaglądania do wnętrza /proc
, /sys
... użyj -xdev
i określ systemy plików, w których chcesz wyszukiwać:
LC_ALL=C find / /home -xdev -type f -exec grep -i 'the brown dog' /dev/null {} +
Lub przycinaj ścieżki, które chcesz jawnie wykluczyć:
LC_ALL=C find / \( -path /dev -o -path /proc -o -path /sys \) -prune -o \
-type f -exec grep -i 'the brown dog' /dev/null {} +