Melyik hatékonyabb annak megtalálásához, hogy a teljes fájlrendszer mely fájljai tartalmaznak sztringet: rekurzív grep vagy grec-el keresés egy exec utasításban? Feltételezem, hogy a keresés hatékonyabb lenne, mert legalább szűrhet, ha ismeri a fájlkiterjesztést vagy a fájlnévnek megfelelő regexet, de ha csak a -type f fájlt tudja, ? GNU grep 2.6.3; find (GNU findutils) 4.4.2

Példa:

grep -r -i "the brown dog" /

find / -type f -exec grep -i "the brown dog" {} \;

Megjegyzések

  • Matematika / informatika / algoritmus hatékonysága ‘ t vélemény alapú.
  • Ellenőrizze ezt. Bár nem rekurzív, megértést adna arról, hogy melyik a jobb. unix.stackexchange.com/questions/47983/…
  • @AvinashRaj he ‘ s nem kér véleményt. ‘ ‘ azt kérdezi, melyik a hatékonyabb és / vagy gyorsabb , nem melyik a ” jobb “. Ez egy tökéletesen megválaszolható kérdés, amelynek egyetlen, konkrét válasza van, amely attól függ, hogy ez a két program hogyan végzi a dolgát, és attól, hogy pontosan mit ad nekik a kereséshez.
  • Ne feledje, hogy a űrlap kevesebb villát fog megtenni, ezért gyorsabbnak kell lennie, mint a -exec {} \;. Előfordulhat, hogy a -H (vagy -h) elemeket hozzá kell adnia a grep opciókhoz, hogy pontosan megkapja. egyenértékű kimenet.
  • Valószínűleg nem ‘ nem akarta az -r beállítást a grep a másodikhoz

Válasz

Nem vagyok biztos benne:

grep -r -i "the brown dog" /* 

erre gondoltál. Ez azt jelentené, hogy rekurzívan grep az összes nem rejtett fájl és mappa a / fájlban (de a rejtett fájlokba és azokba belenézhet).

Feltételezve, hogy ezt értette:

grep -r -i "the brown dog" / 

Néhány megjegyzendő dolog:

  • Nem minden grep megvalósítás támogatja a -r. És az ilyenek között a viselkedés eltér: egyesek a könyvtárakra mutató hivatkozásokat követik a könyvtárfán való áthaladáskor (ami azt jelenti, hogy végül verális idők ugyanabban a fájlban, vagy akár végtelen ciklusokban futnak), egyesek nem. Néhányan belenéznek az eszközfájlokba (és ez például sokáig tart például a /dev/zero fájlokban), vagy a pipe-okban vagy a bináris fájlokban … vannak, akik nem.
  • Hatékony, mivel a grep fájlok belsejébe kezd keresni, amint felfedezi őket. De bár egy fájlban kinéz, már nem keres több fájlt keresésre (amely valószínűleg a legtöbb esetben ugyanolyan jól működik)

Az Ön:

find / -type f -exec grep -i "the brown dog" {} \; 

(eltávolította a aminek itt nem volt értelme) szörnyen nem hatékony, mert fájlonként egy grep fájlt futtat. A ; csak azokhoz a parancsokhoz használható, amelyek csak egy argumentumot fogadnak el. Ráadásul itt, mivel a grep csak egy fájlban néz ki, a fájl nevét nem fogja kinyomtatni, így nem tudhatja, hogy hol vannak az egyezések.

Ön ” nem nézel az eszközfájlokba, csövekbe, szimpla linkekbe …, nem követed a szimpla linkeket, de még mindig olyan dolgokat keresel, mint a /proc/mem.

find / -type f -exec grep -i "the brown dog" {} + 

sokkal jobb lenne, mert a lehető legkevesebb grep parancs futna. Megkapja a fájl nevét, kivéve, ha az utolsó futtatásnak csak egy fájlja van. Ehhez jobb használni:

find / -type f -exec grep -i "the brown dog" /dev/null {} + 

vagy GNU

:

find / -type f -exec grep -Hi "the brown dog" {} + 

Ne feledje, hogy a grep csak find elég fájlt talált ahhoz, hogy rágódjon rajta, ezért lesz némi kezdeti késés. És a find addig nem folytat további fájlok keresését, amíg az előző grep vissza nem tér. A nagy fájllista kiosztásának és átadásának van némi (valószínűleg elhanyagolható) hatása, így összességében valószínűleg kevésbé lesz hatékony, mint egy grep -r, amely nem követi a symlinket vagy a kinézetet az eszközök belsejében.

GNU eszközökkel:

find / -type f -print0 | xargs -r0 grep -Hi "the brown dog" 

A fentiek szerint néhány grep a lehetséges példányok futtatásra kerülnek, de a find folytatja a további fájlok keresését, míg az első grep meghívás az első köteg belsejében keres. Ez lehet vagy nem előny.Például forgó merevlemezeken tárolt adatok esetén a find és a grep lemez különböző helyein tárolt adatokhoz való hozzáférés lelassítja a lemezt áteresztőképességet a lemezfej állandó mozgatásával RAID-beállításban (ahol find és grep különböző lemezekhez férhet hozzá) vagy SSD-ken ez pozitív változást eredményezhet.

RAID-beállításban több egyidejű grep meghívás futtatása is javíthat a dolgon. A RAID1 tárhelyen lévő 3 lemezes GNU eszközök mellett továbbra is

find / -type f -print0 | xargs -r0 -P2 grep -Hi "the brown dog" 

jelentősen növelheti a teljesítményt. Vegye figyelembe azonban, hogy a második grep csak akkor indul el, ha elegendő fájl található az első grep parancs kitöltéséhez. Hozzáadhat egy -n beállítást a xargs elemhez, hogy ez hamarabb megtörténjen (és kevesebb fájlt adjon át grep invokáció).

Vegye figyelembe azt is, hogy ha a xargs kimenetet másra irányítja, csak egy végberendezésre, akkor a greps s megkezdi a kimenetük pufferelését, ami azt jelenti, hogy valószínűleg a grep k kimenetét helytelenül fogják összeszövni. A következőt kell használni: >

(ahol elérhető, mint például a GNU vagy a FreeBSD-n) rájuk, hogy kiküszöböljék ezt (még mindig nagyon hosszú sorokkal lehetnek problémáid (általában> 4KiB)), vagy mindegyiket külön fájlba kell írniuk, és összefűzni őket a végén.

Itt a keresett karakterlánc javítva van (nem regexp), így a -F opció használata változást hozhat (valószínűtlen, mint A grep implementációk már tudják ezt optimalizálni).

Egy másik dolog, amit Nagy különbség van a területi beállítás C-re történő javítása, ha több bájtos terepen van:

find / -type f -print0 | LC_ALL=C xargs -r0 -P2 grep -Hi "the brown dog" 

A , /sys …, használja a -xdev elemet, és adja meg a keresni kívánt fájlrendszereket:

LC_ALL=C find / /home -xdev -type f -exec grep -i "the brown dog" /dev/null {} + 

Vagy metszeni a kizárni kívánt utakat kifejezetten:

LC_ALL=C find / \( -path /dev -o -path /proc -o -path /sys \) -prune -o \ -type f -exec grep -i "the brown dog" /dev/null {} + 

megjegyzések

  • Nem feltételezem, hogy valaki rám utalhat egy erőforrásra – vagy megmagyarázza -, mit jelent a {} és a +. ‘ nincs semmi, amit nem látok a man oldalakon exec, grep vagy a Solaris mezőben, amit i ‘ m használok. Csak a héj összefűzi a fájlneveket és továbbítja őket a grephez?
  • @Poldie, ezt ‘ egyértelműen megmagyarázza a predikátum a Solaris man oldalon
  • Ah, igen. Nem ‘ nem menekültem el a {char-ból, miközben a man oldalon keresgéltem. A linked jobb; Szörnyűnek tartom a man oldalakat.
  • RAID1 w / 3 lemezekkel? Mennyire furcsa …
  • @tink, igen A RAID1 legalább 2 lemezen van. Három lemezzel 2 lemezhez képest növeli a redundanciát és az olvasási teljesítményt, miközben az írási teljesítmény nagyjából megegyezik. 3 lemezzel szemben a 2-vel szemben ez azt jelenti, hogy a hibákat is kijavíthatja, mivel amikor egy kicsit átfordítja az egyik példányt, ‘ az összes ellenőrzésével meg tudja mondani, hogy mi a helyes. 3 példány, míg 2 lemezzel ‘ nem tudja igazán elmondani.

Válasz

Ha a * a grep hívásban nem fontos az Ön számára, akkor az elsőnek hatékonyabbnak kell lennie, mivel csak egy a grep példány elindul, és a villák nem szabadok. A legtöbb esetben még a * esetén is gyorsabb lesz, de szélső esetekben a rendezés ezt megfordíthatja.

Lehetnek más findgrep struktúrák, amelyek különösen sok kicsi esetén működnek jobban. fájlok. Nagy mennyiségű fájlbejegyzés és inode egyszerre történő elolvasása javíthatja a forgatható adathordozókat.

De nézzük át a syscall statisztikáit:

> strace -cf find . -type f -exec grep -i -r "the brown dog" {} \; % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 97.86 0.883000 3619 244 wait4 0.53 0.004809 1 9318 4658 open 0.46 0.004165 1 6875 mmap 0.28 0.002555 3 977 732 execve 0.19 0.001677 2 980 735 stat 0.15 0.001366 1 1966 mprotect 0.09 0.000837 0 1820 read 0.09 0.000784 0 5647 close 0.07 0.000604 0 5215 fstat 0.06 0.000537 1 493 munmap 0.05 0.000465 2 244 clone 0.04 0.000356 1 245 245 access 0.03 0.000287 2 134 newfstatat 0.03 0.000235 1 312 openat 0.02 0.000193 0 743 brk 0.01 0.000082 0 245 arch_prctl 0.01 0.000050 0 134 getdents 0.00 0.000045 0 245 futex 0.00 0.000041 0 491 rt_sigaction 0.00 0.000041 0 246 getrlimit 0.00 0.000040 0 489 244 ioctl 0.00 0.000038 0 591 fcntl 0.00 0.000028 0 204 188 lseek 0.00 0.000024 0 489 set_robust_list 0.00 0.000013 0 245 rt_sigprocmask 0.00 0.000012 0 245 set_tid_address 0.00 0.000000 0 1 uname 0.00 0.000000 0 245 fchdir 0.00 0.000000 0 2 1 statfs ------ ----------- ----------- --------- --------- ---------------- 100.00 0.902284 39085 6803 total 

csak grep

> strace -cf grep -r -i "the brown dog" . % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 40.00 0.000304 2 134 getdents 31.71 0.000241 0 533 read 18.82 0.000143 0 319 6 openat 4.08 0.000031 4 8 mprotect 3.29 0.000025 0 199 193 lseek 2.11 0.000016 0 401 close 0.00 0.000000 0 38 19 open 0.00 0.000000 0 6 3 stat 0.00 0.000000 0 333 fstat 0.00 0.000000 0 32 mmap 0.00 0.000000 0 4 munmap 0.00 0.000000 0 6 brk 0.00 0.000000 0 2 rt_sigaction 0.00 0.000000 0 1 rt_sigprocmask 0.00 0.000000 0 245 244 ioctl 0.00 0.000000 0 1 1 access 0.00 0.000000 0 1 execve 0.00 0.000000 0 471 fcntl 0.00 0.000000 0 1 getrlimit 0.00 0.000000 0 1 arch_prctl 0.00 0.000000 0 1 futex 0.00 0.000000 0 1 set_tid_address 0.00 0.000000 0 132 newfstatat 0.00 0.000000 0 1 set_robust_list ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000760 2871 466 total 

megjegyzések

  • A teljes fájlrendszer keresésének skáláján a villák elhanyagolhatóak. Az I / O-t csökkenteni szeretné.
  • Bár hiba az OP-ban, az összehasonlítás helytelen, el kell távolítania a -r zászlót div id = “2b5be2b501”>

afindhasználatakor. Láthatja, hogy ugyanazon fájlokban keresett újra és újra, összehasonlítva a megtörténtopenszámot.

  • @qwertzguy, nem, az -r ártalmatlannak kell lennie, mivel a -type f nem garantálja, hogy az egyik argumentum sem könyvtár. A többszörös open() s valószínűleg a grep által minden egyes meghíváskor megnyitott többi fájlhoz tartozik (könyvtárak, lokalizációs adatok …) ( köszönöm a szerkesztést a válaszomra btw)
  • Válasz

    Ha SSD-t használsz és időt keresel elhanyagolható, használhatná a GNU párhuzamot:

    find /path -type f | parallel --gnu --workdir "$PWD" -j 8 " grep -i -r "the brown dog" {} " 

    Ez akár 8 grep folyamatot is végrehajt egyidejűleg a megtalálva.

    Ez megsemmisíti a merevlemez-meghajtót, de az SSD-nek elég jól kell megbirkóznia vele.

    Válasz

    Ebben a tekintetben még egy szempontot figyelembe kell venni.

    Tartalmaz-e többet azok a könyvtárak, amelyeket grep nek rekurzívan kell átnéznie? fájlokat, mint a rendszer nofile beállítását? (pl. a megnyitott fájlkezelők száma, alapértelmezés szerint 1024 a legtöbb linuxos disztribúción)

    Ha igen, akkor a find mindenképpen a megfelelő út, mivel a grep egy argumentumlista túl hosszú hibával fordul elő, ha olyan könyvtárba ütközik, amelynek több fájlja van, mint a maximálisan megnyitott fájl kezeli a beállítást.

    Csak az én 2-esem.

    Megjegyzések

    • Miért lenne grep bombázni? Legalább a GNU grep használatával, ha megad egy utat / és a -R it egyszerûen végigmegyek a könyvtárakon keresztül. A shell nem fog ‘ bővíteni semmit, hacsak nem ad meg shell-globusokat. Tehát az adott példában (/*) csak a / tartalma számít, nem pedig azok az almappák, amelyeket egyszerűen felsorol a grep, nem került átadásra argumentumként a héjból.
    • Nos, figyelembe véve az OP-t, a rekurzív keresés kérdése volt (pl. -r -i ‘ a barna kutya ‘ / * “), láttam A GNU ‘ s grep (legalább a 2.9-es verzió) bomba: ” -bash: / bin / grep: Az argumentumlista túl hosszú ” az OP pontos keresésével egy olyan könyvtárban, amelyben több mint 140 000 alkönyvtár volt.

    Vélemény, hozzászólás?

    Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük