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
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 find
– grep
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”>
afind
használatakor. Láthatja, hogy ugyanazon fájlokban keresett újra és újra, összehasonlítva a megtörténtopen
számot.
-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
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 agrep
, 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.
-exec {} \;
. Előfordulhat, hogy a-H
(vagy-h
) elemeket hozzá kell adnia agrep
opciókhoz, hogy pontosan megkapja. egyenértékű kimenet.-r
beállítást agrep
a másodikhoz