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ýsledku find, zatímco shoda s find -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. S find filename by byla zkoumána pouze filename (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

  • find filename vrátí pouze filename pokud filename nebyl typu adresář (nebo byl typu adresář, ale sám neměl žádný záznam)

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íše jack pokud se ‚ sahá soubor jack nebo všechna jména v adresáři, pokud je ‚ sa adresář. ‚ je nedorozuměním toho, jak find 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á verze find …)
  • @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' zpomaluje find? 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.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *