GNU/Linux >> Znalost Linux >  >> Linux

Rekurzivní Grep vs Find / -type F -exec Grep {}; Co je efektivnější/rychlejší?

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í.

Související:Jak fungují ${0##*/} a ${0%/*}?

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 {} +

Linux
  1. Získání možnosti -exec v aplikaci Najít do práce?

  2. Vymanit se z hledání, pokud selže -exec?

  3. Jak najít více řetězců v souborech?

  1. najít -exec funkci shellu v Linuxu?

  2. Efektivní způsob, jak najít task_struct pomocí pid

  3. Jak zjistit, který proces používá soubor v Linuxu?

  1. Najít vyloučený adresář?

  2. rekurzivní grep:vyloučení konkrétních adresářů

  3. Nalezení adresáře v linuxovém terminálu