Jeg prøvede begge kommandoer, og kommandoen find | grep "filename" er mange mange gange langsommere end den enkle find "filename" kommando.

Hvad ville være en korrekt forklaring på denne adfærd?

Kommentarer

  • Dig viser hver fil med find og videregiver derefter dataene til grep for at behandle dem. Med find brugt på det ‘ s eget, mangler du trinnet med at videresende alle listede filer til grep for at analysere output. Dette vil derfor være hurtigere.
  • Langsom i hvilken forstand? Det tager forskellige tid at udføre kommandoerne?
  • Jeg kan ‘ t gengive dette lokalt. Hvis der er noget, rapporterer time find "$HOME" -name '.profile' længere tid end time find "$HOME" | grep -F '.profile'. (17ere mod 12ere).
  • @JenniferAnderson Jeg løb begge gentagne gange. 17 og 12 sekunder er gennemsnit. Og ja, grep variationen vil matche hvor som helst i find resultatet, mens matchning med find -name ville kun matche nøjagtigt (i dette tilfælde).
  • Ja, find filename ville være hurtig . Jeg antog lidt, at dette var en skrivefejl, og at OP betød find -name filename. Med find filename ville kun filename blive undersøgt (og intet andet).

Svar

(Jeg antager, at GNU find her)

Brug bare

find filename 

ville være hurtig, fordi det bare ville returnere filename, eller navnene inde i filename hvis det er en mappe, eller en fejl, hvis navnet ikke eksisterede i den aktuelle mappe. Det er en meget hurtig betjening svarende til ls filename (men rekursiv, hvis filename er et bibliotek).

I kontrast

find | grep filename 

ville tillade find at generere en liste med alle navne fra det aktuelle bibliotek og derunder, som grep derefter ville filtrere. Dette ville naturligvis være en meget langsommere handling.

Jeg antager, at hvad der var faktisk beregnet var

find . -type f -name "filename" 

Dette ville se efter filename som navnet på en almindelig fil hvor som helst i det aktuelle bibliotek eller derunder.

Dette vil være lige så hurtigt (eller sammenligneligt hurtigt) som find | grep filename, men grep løsning ville matche filename mod den fulde sti for hvert fundet navn, på samme måde som -path "*filename*" ville gøre med find.


Forvirringen kommer fra en misforståelse af, hvordan find fungerer.

Hjælpeprogrammet tager et antal stier og returnerer alle navne under disse stier.

Du kan derefter begrænse de returnerede navne ved hjælp af forskellige tests, der kan virke på filnavnet, stien, tidsstemplet, filstørrelsen, filtypen osv.

Når du siger

find a b c 

du beder find om at liste hvert tilgængeligt navn under de tre stier a, b og c. Hvis dette tilfældigvis er navne på almindelige filer i den aktuelle mappe, returneres disse. Hvis nogen af dem tilfældigvis er navnet på en mappe, returneres den sammen med alle yderligere navne i den mappe.

Når jeg gør

find . -type f -name "filename" 

Dette genererer en liste med alle navne i den aktuelle mappe (.) og derunder. Derefter begrænser det navnene til almindelige filer, dvs. ikke mapper osv., Med -type f. Derefter er der en yderligere begrænsning af navne, der matcher filename ved hjælp af -name "filename". Strengen filename kan være et filnavnet globbing mønster, såsom *.txt (husk bare at citere det!).

Eksempel:

Følgende synes at “finde” filen med navnet .profile i min hjemmekatalog:

$ pwd /home/kk $ find .profile .profile 

Men faktisk returnerer det bare alle navne på stien .profile (der er kun ét navn, og det er denne fil).

cd et niveau op og prøv igen:

$ cd .. $ pwd /home $ find .profile find: .profile: No such file or directory 

find -kommandoen kan nu ikke finde nogen sti, der hedder .profile.

Men hvis jeg får det til at se på den aktuelle mappe og derefter begrænser de returnerede navne til kun .profile , finder den det derfra også:

$ pwd /home $ find . -name ".profile" ./kk/.profile 

Kommentarer

  • find filename ville kun returnere filename hvis filename ikke var af typen katalog (eller var af typen katalog, men havde ikke nogen post i sig selv)

Svar

Ikke-teknisk forklaring: På udkig efter Jack i en skare er hurtigere end at lede efter alle i en skare og fjerne alle fra overvejelse undtagen Jack.

Kommentarer

  • Problemet er, at OP forventer, at Jack skal være den eneste person i mængden. Hvis det er tilfældet, er de ‘ heldige. find jack viser jack hvis det ‘ en fil med navnet jack eller alle navne i biblioteket, hvis det ‘ er et bibliotek. Det ‘ er en misforståelse af, hvordan find fungerer.

Svar

Jeg har ikke forstået problemet endnu, men kan give nogle flere indsigter.

Ligesom for Kusalananda kaldes find | grep er klart hurtigere på mit system, hvilket ikke giver meget mening. Først antog jeg en form for bufferingsproblem; at skrivning til konsollen bremser tiden til næste syscall til læsning af det næste filnavn. At skrive til et rør er meget hurtigt: ca. 40MiB / s selv til 32-byte-skrivning (på mit ret langsomme system; 300 MiB / s for en blokstørrelse på 1MiB). Jeg antog således, at find kan læse fra filsystemet hurtigere, når man skriver til et rør (eller en fil), så de to operationer, der læser filstier og skriver til konsollen, kan køre parallelt ( som find som en enkelt trådproces ikke kan gøre alene.

Det “s find “s fejl

Sammenligning af de to opkald

:> time find "$HOME"/ -name "*.txt" >/dev/null real 0m0.965s user 0m0.532s sys 0m0.423s 

og

:> time find "$HOME"/ >/dev/null real 0m0.653s user 0m0.242s sys 0m0.405s 

viser, at find gør noget utroligt dumt (hvad det måtte være). viser sig at være ret inhabil ved udførelse af -name "*.txt".

Kan afhænge af input / output-forholdet

Du tror måske, at find -name vinder, hvis der er meget lidt at skrive. Men jeg bliver bare mere pinligt for find. Det taber, selvom der slet ikke er noget at skrive mod 200K filer (13M rørdata) for grep:

time find /usr -name lwevhewoivhol 

find kan være så hurtig som grep, selvom

Det viser sig, at find “s dumhed med name ikke udvides til andre tests. Brug en regex i stedet, og problemet er væk:

:> time find "$HOME"/ -regex "\.txt$" >/dev/null real 0m0.679s user 0m0.264s sys 0m0.410s 

Jeg antager, at dette kan betragtes som en fejl. Er nogen villige til at indgive en fejlrapport? Min version er find (GNU findutils) 4.6.0

Kommentarer

  • Hvor gentagelige er dine timinger? Hvis du først testede -name, kan det have været langsommere på grund af biblioteksindholdet, der ikke blev cache. (Når vi tester -name og -regex finder jeg, at de tager omtrent samme tid, i det mindste når cacheeffekten er taget i betragtning. selvfølgelig kan det bare være en anden version af find …)
  • @psmears Selvfølgelig har jeg lavet disse tests flere gange. Cache-problemet er blevet nævnt selv i kommentarerne til spørgsmålet før det første svar. Min find version er find (GNU findutils) 4.6.0
  • Hvorfor er det overraskende at tilføje -name '*.txt' find? Det skal udføre ekstra arbejde ved at teste hvert filnavn.
  • @Barmar På den ene side kan dette ekstra arbejde udføres ekstremt hurtigt. På den anden side sparer dette ekstra arbejde andet arbejde. find skal skrive færre data. Og at skrive til et rør er en meget langsommere handling.
  • At skrive til en disk er meget langsom, at skrive til et rør er ikke så slemt, det kopieres bare til en kernebuffer. Bemærk, at du ved din første test ved at skrive mere til /dev/null på en eller anden måde brugte mindre systemtid.

Svar

Bemærk : Jeg antager, at du mener find . -name filename (ellers leder du efter forskellige ting; find filename ser faktisk på en sti kaldet filnavn , som indeholder muligvis næsten ingen filer og afsluttes derfor meget hurtigt).


Antag at du har en mappe med fem tusind filer. På de fleste filsystemer er disse filer faktisk gemt i en træ struktur , som gør det muligt hurtigt at finde en given fil.

Så når du beder find om at finde en fil, hvis navn kun kræver kontrol, vil find spørge til den fil, og kun den fil, til det underliggende filsystem, som vil læse meget få sider fra masselagring. Så hvis filsystemet er saltet værd, kører denne handling meget hurtigere end , der gennemgår hele træet for at hente alle poster.

Når du beder om almindelig find men det er nøjagtigt hvad du laver, krydser du hele træet og læser. Hver. Enkel. Indgang. Med store mapper, dette kan være et problem (det er nøjagtigt grunden til, at flere software, der har brug for at gemme mange filer på disken, vil skabe “katalogtræer” to eller tre komponenter dybt: på denne måde behøver hvert enkelt blad kun at holde færre filer) .

Svar

Lad os antage, at filen / john / paul / george / ringo / beatles findes, og den fil du søger efter kaldes “sten”

find / stones 

find vil sammenligne “beatles” med “sten” og droppe det, når “s” og “b” ikke matcher .

find / | grep stones 

I dette tilfælde finder vil passere “/ john / paul / george / ringo / beatles” til grep og grep wil Jeg er nødt til at arbejde sig gennem hele stien, før jeg bestemmer, om det er et match.

grep gør derfor langt mere arbejde, hvorfor det tager længere tid

Kommentarer

  • Har du prøvet det?
  • Omkostningerne ved strengesammenligninger (ekstremt enkle og billige) er helt dværg af IO (eller bare syscall hvis cache) omkostninger af katalogopslag.
  • grep isn ‘ ta-sammenligning af streng, dens sammenligning med regelmæssigt udtryk, hvilket betyder, at den skal arbejde sig gennem hele strengen, indtil den enten finder en kamp eller når slutningen. Katalogopslag er de samme uanset hvad.
  • @Paranoid Hm, hvilken version af find taler du om? Det ‘ er tilsyneladende ikke noget som find I ‘ plejede at være i debian.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *