Zkoušel jsem oba příkazy a příkaz find | grep "filename"
je mnohokrát pomalejší než jednoduchý .
Jaké by bylo správné vysvětlení tohoto chování?
Komentáře
- Vy vypisují každý soubor s vyhledáním a poté předávají data ke zpracování grep. Při hledání použitého ‚ s vlastním vám chybí krok předání každého uvedeného souboru grepu pro analýzu výstupu. Bude to tedy rychlejší.
- V jakém smyslu pomalejší? Trvá provedení příkazů jinou dobu?
- Nemohu to ‚ lokálně reprodukovat. Pokud nic,
time find "$HOME" -name '.profile'
hlásí delší dobu nežtime find "$HOME" | grep -F '.profile'
. (17 s vs. 12 s). - @JenniferAnderson Oba jsem běžel opakovaně. 17 a 12 sekund jsou průměry. A ano,
grep
variace bude odpovídat kdekoli ve výsledkufind
, zatímco shoda sfind -name
by odpovídalo pouze přesně (v tomto případě). - Ano,
find filename
by bylo rychlé . Trochu jsem předpokládal, že se jedná o překlep a že OP znamenáfind -name filename
. Sfind filename
by byla zkoumána pouzefilename
(a nic jiného).
Odpovědět
(Předpokládám GNU find
zde)
Použít pouze
find filename
by by bylo rychlé, protože by vrátilo filename
nebo jména uvnitř filename
pokud je to adresář, nebo chyba, pokud tento název v aktuálním adresáři neexistoval. Je to velmi rychlá operace podobná ls filename
(ale rekurzivní, pokud filename
je adresář).
V Naproti tomu
find | grep filename
by umožnilo find
vygenerovat seznam všech jmen z aktuální adresář a níže, který by grep
filtroval. To by samozřejmě byla mnohem pomalejší operace.
Předpokládám, že to, co bylo ve skutečnosti zamýšleno bylo
find . -type f -name "filename"
Toto by hledalo filename
jako název běžného souboru kdekoli v aktuální adresář nebo níže.
Bude to tak rychlé (nebo srovnatelně rychlé) jako find | grep filename
, ale grep
řešení by porovnalo filename
s celou cestou každého nalezeného jména, podobně jako -path "*filename*"
s find
.
Zmatek vychází z nedorozumění toho, jak find
funguje.
Nástroj převezme několik cest a vrátí všechny názvy pod těmito cestami.
Poté můžete omezit vrácená jména pomocí různých testů, které mohou působit na název souboru, cestu, časové razítko, velikost souboru, typ souboru atd.
Když řeknete
find a b c
požádáte find
o seznam všech dostupných jmen pod třemi cestami a
, b
a c
. Pokud se jedná o názvy běžných souborů v aktuálním adresáři, budou vráceny. Pokud je některý z nich název adresáře, bude vrácen spolu se všemi dalšími jmény v tomto adresáři.
Když to udělám
find . -type f -name "filename"
Tím se vygeneruje seznam všech jmen v aktuálním adresáři (.
) a níže. Potom omezuje názvy na běžné soubory, tj. Ne adresáře atd., Pomocí -type f
. Pak existuje další omezení na jména, která odpovídají filename
pomocí -name "filename"
. Řetězec filename
může být vzor globování souboru, například *.txt
(nezapomeňte jej uvést!).
Příklad:
Zdá se, že „najdu“ soubor s názvem .profile
v mém domovském adresáři:
$ pwd /home/kk $ find .profile .profile
Ve skutečnosti ale vrátí pouze všechna jména na cestě .profile
(existuje pouze jedno jméno, a to z tohoto souboru).
Pak jsem cd
o jednu úroveň výš a zkuste to znovu:
$ cd .. $ pwd /home $ find .profile find: .profile: No such file or directory
nyní nemůže najít žádnou cestu nazvanou .profile
.
Pokud se však podívám na aktuální adresář a poté omezím vrácená jména pouze na .profile
, zjistí i odtud:
$ pwd /home $ find . -name ".profile" ./kk/.profile
Komentáře
Odpověď
Netechnické vysvětlení: Hledáme Jacka v davu je rychlejší než hledat všechny v davu a eliminovat všechny z úvah kromě Jacka.
Komentáře
- Problém je v tom, že OP očekává, že Jack být jedinou osobou v davu. Pokud ano, mají ‚ štěstí.
find jack
vypíšejack
pokud se ‚ sahá souborjack
nebo všechna jména v adresáři, pokud je ‚ sa adresář. ‚ je nedorozuměním toho, jakfind
funguje.
Odpověď
Dosud jsem nepochopil problém, ale mohu poskytnout několik dalších poznatků.
Stejně jako v případě Kusalanandy je volání find | grep
je v mém systému jasně rychlejší, což nedává moc smysl. Nejprve jsem předpokládal nějaký problém s vyrovnávací pamětí; že zápis do konzoly zpomaluje čas do dalšího volání Syscall pro čtení názvu dalšího souboru. Zápis do kanálu je velmi rychlý: asi 40 Mb / s i pro 32bajtové zápisy (na mém poměrně pomalém systému; 300 MiB / s pro velikost bloku 1 Mb). Předpokládal jsem tedy, že find
umí číst ze systému souborů rychleji při zápisu do kanálu (nebo souboru), takže obě operace čtení cest k souborům a zápis do konzoly mohly běžet paralelně ( což find
jako proces s jedním vláknem sám o sobě nedokáže.
Je to „
Porovnání obou hovorů
:> time find "$HOME"/ -name "*.txt" >/dev/null real 0m0.965s user 0m0.532s sys 0m0.423s
a
:> time find "$HOME"/ >/dev/null real 0m0.653s user 0m0.242s sys 0m0.405s
ukazuje, že find
dělá něco neuvěřitelně hloupého (ať je to cokoli). se při provádění -name "*.txt"
ukazuje jako zcela nekompetentní.
Může to záviset na poměru vstup / výstup
Možná si myslíte, že find -name
vyhraje, pokud je toho málo na psaní. Ale pro find
. Ztrácí, i když není vůbec co psát proti 200 tis. souborům (13 mil. dat potrubí) pro grep
:
time find /usr -name lwevhewoivhol
find
může být tak rychlý jako grep
, i když
Ukázalo se, že hloupost find
s name
se nevztahuje na další testy. Místo toho použijte regex a problém je pryč:
:> time find "$HOME"/ -regex "\.txt$" >/dev/null real 0m0.679s user 0m0.264s sys 0m0.410s
Myslím, že to lze považovat za chybu. Každý, kdo je ochoten podat hlášení o chybě? Moje verze je find (GNU findutils) 4.6.0
Komentáře
- Jak opakovatelná jsou vaše načasování? Pokud jste nejprve provedli
-name
test, mohl být pomalejší, protože obsah adresáře nebyl uložen do mezipaměti. (Při testování-name
a-regex
zjišťuji, že to trvá zhruba ve stejnou dobu, alespoň jednou byl zohledněn efekt mezipaměti. samozřejmě to může být jen jiná verzefind
…) - @psmears Tyto testy jsem samozřejmě provedl několikrát. Problém ukládání do mezipaměti byl zmíněn dokonce i v komentářích k otázce před první odpovědí. Moje
find
verze je find (GNU findutils) 4.6.0 - Proč je překvapivé, že přidání
-name '*.txt'
zpomalujefind
? Musí to udělat práci navíc, testování každého názvu souboru. - @Barmar Tuto práci navíc lze na jedné straně provést extrémně rychle. Na druhou stranu tato práce navíc ušetří další práci.
find
musí zapisovat méně dat. A zápis do kanálu je mnohem pomalejší operace. - Zápis na disk je velmi pomalý, zápis do kanálu není tak špatný, pouze se zkopíruje do vyrovnávací paměti jádra. Všimněte si, že ve vašem prvním testu psaní více do
/dev/null
nějak spotřebovalo méně systémového času.
Odpověď
Upozornění : Předpokládám, že máte na mysli find . -name filename
(jinak hledáte různé věci; find filename
se vlastně dívá do cesty s názvem název , který nemusí obsahovat téměř žádné soubory, takže se ukončí opravdu rychle).
Předpokládejme, že máte adresář obsahující pět tisíc souborů. Ve většině souborových systémů jsou tyto soubory skutečně uloženy ve stromové struktuře , která umožňuje rychle vyhledat libovolný daný soubor.
Když tedy find
požádáte o vyhledání souboru, jehož název vyžaduje pouze kontrolu, find
em pro tento soubor a pouze tento soubor do základního souborového systému, který přečte z velkokapacitního úložiště velmi málo stránek. Pokud tedy souborový systém stojí za jeho sůl, tato operace poběží mnohem rychleji než procházení celého stromu k načtení všech položek.
Když žádáte o prostý find
jakkoli přesně to, co děláte, projdete celý strom a budete číst. Každý. Jeden. Vstup. S velkými adresáři, to by mohl být problém (to je přesně ten důvod, proč několik softwarů, které potřebují uložit spoustu souborů na disk, vytvoří hluboko dva nebo tři komponenty „adresářových stromů“: takto musí každý list obsahovat pouze méně souborů) .
Odpovědět
Předpokládejme, že existuje soubor / john / paul / george / ringo / beatles a soubor, který hledáte se nazývá „kameny“
find / stones
find porovná „beatles“ s „kameny“ a vypustí je, když se „s“ a „b“ nebudou shodovat .
find / | grep stones
V tomto případě funkce find předá „/ john / paul / george / ringo / beatles“ grep a grep wil Než zjistím, zda je to shoda, musím si projít celou cestu.
grep proto dělá mnohem více práce, a proto to trvá déle
Komentáře
- Zkoušeli jste to?
- Náklady na porovnání řetězců (extrémně jednoduché a levné) jsou zcela zakrslé náklady na vstup / výstup (nebo pouze syscall, pokud je v mezipaměti) vyhledávání adresářů.
- grep isn ‚ ta porovnání řetězců, porovnání s regulárním výrazem, což znamená, že se musí propracovat celým řetězcem, dokud nenajde zápas nebo dosáhne konce. Vyhledávání adresářů je stejné bez ohledu na to.
- @Paranoid Hm, o jaké verzi find mluvíš? Zdá se, že to ‚ není nic jako find I ‚ m v debianu.
find filename
vrátí pouzefilename
pokudfilename
nebyl typu adresář (nebo byl typu adresář, ale sám neměl žádný záznam)