Co je efektivnější pro zjištění, které soubory v celém souborovém systému obsahují řetězec:rekurzivní grep nebo find pomocí grep v příkazu exec? Předpokládám, že hledání by bylo efektivnější, protože můžete alespoň provést nějaké filtrování, pokud znáte příponu souboru nebo regulární výraz, který odpovídá názvu souboru, ale když znáte pouze -type f
který je lepší? GNU grep 2.6.3; find (GNU findutils) 4.4.2
Příklad:
grep -r -i 'the brown dog' /
find / -type f -exec grep -i 'the brown dog' {} ;
Přijatá odpověď:
Nejsem si jistý:
grep -r -i 'the brown dog' /*
je opravdu to, co jsi myslel. To by znamenalo grep rekurzivně ve všech neskrytých souborech a adresářích v /
(ale stále se podívejte do skrytých souborů a adresářů uvnitř nich).
Za předpokladu, že jste mysleli:
grep -r -i 'the brown dog' /
Několik poznámek:
- Ne všechny
grep
implementace podporují-r
. A mezi těmi, kteří ano, se chování liší:někteří se při procházení stromem adresářů řídí symbolickými odkazy na adresáře (což znamená, že můžete skončit několikrát ve stejném souboru nebo dokonce běhat v nekonečných smyčkách), někteří ne. Někteří se podívají do souborů zařízení (a v/dev/zero
to bude nějakou dobu trvat například) nebo roury nebo binární soubory…, některé ne. - Je to efektivní jako
grep
začne prohledávat soubory, jakmile je objeví. Ale zatímco hledá v souboru, už nehledá další soubory k prohledávání (což je pravděpodobně ve většině případů stejně dobře)
Váš:
find / -type f -exec grep -i 'the brown dog' {} ;
(odstraněno -r
který zde nedával smysl) je strašně neefektivní, protože provozujete jeden grep
na soubor. ;
by měl být použit pouze pro příkazy, které přijímají pouze jeden argument. Navíc zde, protože grep
hledá pouze v jednom souboru, nevytiskne název souboru, takže nebudete vědět, kde jsou shody.
Nedíváte se do souborů zařízení, kanálů, symbolických odkazů..., nesledujete symbolické odkazy, ale stále se potenciálně díváte do věcí, jako je /proc/mem
.
find / -type f -exec grep -i 'the brown dog' {} +
by bylo mnohem lepší, protože jen málo grep
budou spuštěny příkazy, jak je to jen možné. Dostanete název souboru, pokud poslední spuštění nemá pouze jeden soubor. K tomu je lepší použít:
find / -type f -exec grep -i 'the brown dog' /dev/null {} +
nebo pomocí GNU grep
:
find / -type f -exec grep -Hi 'the brown dog' {} +
Všimněte si, že grep
nebude spuštěn, dokud find
našel dostatek souborů, aby je mohl rozkousat, takže dojde k určitému počátečnímu zpoždění. A find
nebude pokračovat ve vyhledávání dalších souborů až do předchozího grep
Vrátil se. Přidělování a předávání velkého seznamu souborů má určitý (pravděpodobně zanedbatelný) dopad, takže celkově to bude pravděpodobně méně efektivní než grep -r
který nenásleduje symbolický odkaz ani nenahlíží do zařízení.
S nástroji GNU:
find / -type f -print0 | xargs -r0 grep -Hi 'the brown dog'
Jako výše, jen málo grep
instance budou spuštěny, ale find
bude pokračovat v hledání dalších souborů, zatímco první grep
vyvolání se dívá do první dávky. To ale může a nemusí být výhoda. Například u dat uložených na rotačních pevných discích find
a grep
přístup k datům uloženým na různých místech na disku zpomalí propustnost disku tím, že způsobí neustálý pohyb hlavy disku. V nastavení RAID (kde find
a grep
může přistupovat k různým diskům) nebo na SSD, což může mít pozitivní vliv.
V nastavení RAID běží několik současně grep
invokace mohou také věci zlepšit. Stále s nástroji GNU na úložišti RAID1 se 3 disky,
find / -type f -print0 | xargs -r0 -P2 grep -Hi 'the brown dog'
může výrazně zvýšit výkon. Všimněte si však, že druhý grep
bude spuštěn až poté, co bude nalezen dostatek souborů pro vyplnění prvního grep
příkaz. Můžete přidat -n
možnost xargs
aby k tomu došlo dříve (a předalo méně souborů na grep
vyvolání).
Pamatujte také, že pokud přesměrováváte xargs
výstup na cokoliv kromě koncového zařízení, pak greps
s začne ukládat do vyrovnávací paměti jejich výstup, což znamená, že výstup těchto grep
s bude pravděpodobně nesprávně proloženo. Budete muset použít stdbuf -oL
(je-li k dispozici jako na GNU nebo FreeBSD) na nich, abyste to obešli (stále můžete mít problémy s velmi dlouhými řádky (obvykle>4KiB)), nebo nechte každý zapsat svůj výstup do samostatného souboru a všechny je nakonec zřetězit.
Zde je řetězec, který hledáte, pevný (ne regexp), takže pomocí -F
volba může mít rozdíl (nepravděpodobné jako grep
implementace již vědí, jak to optimalizovat).
Další věcí, která by mohla znamenat velký rozdíl, je oprava národního prostředí na C, pokud jste ve vícebajtovém národním prostředí:
find / -type f -print0 | LC_ALL=C xargs -r0 -P2 grep -Hi 'the brown dog'
Abyste se nemuseli dívat do /proc
, /sys
…, použijte -xdev
a zadejte systémy souborů, ve kterých chcete hledat:
LC_ALL=C find / /home -xdev -type f -exec grep -i 'the brown dog' /dev/null {} +
Nebo ořízněte cesty, které chcete explicitně vyloučit:
LC_ALL=C find / ( -path /dev -o -path /proc -o -path /sys ) -prune -o
-type f -exec grep -i 'the brown dog' /dev/null {} +