Yritin molempia komentoja ja komento find | grep "filename" on monta kertaa hitaampi kuin yksinkertainen find "filename" -komento.

Mikä olisi oikea selitys tälle toiminnalle?

Kommentit

  • Sinä luetellaan kaikki tiedostot löytöineen ja välitetään sitten tiedot grep-käsittelyyn. Kun sitä käytetään ’ omalla, et menetä vaihetta, jonka mukaan jokainen luettelossa oleva tiedosto syötetään grepiksi, jotta jäsennetään lähtö. Näin tapahtuu nopeammin.
  • Missä mielessä hitaammin? Tarvitseeko komentojen suorittamiseen eri aika?
  • En voi ’ tuottaa tätä paikallisesti. Jos jotain, time find "$HOME" -name '.profile' raportoi pidemmän ajan kuin time find "$HOME" | grep -F '.profile'. (17s vs. 12s).
  • @JenniferAnderson juoksin molemmat toistuvasti. 17 ja 12 sekuntia ovat keskiarvoja. Ja kyllä, grep -vaihtoehto sopii mihin tahansa find -tulokseen, kun taas vastaavuus find -name sopisi vain tarkalleen (tässä tapauksessa).
  • Kyllä, find filename olisi nopeaa . Oletin, että tämä oli kirjoitusvirhe ja että OP tarkoitti find -name filename. Kohdassa find filename vain filename tutkitaan (eikä mitään muuta).

Vastaa

(Oletan, että GNU find täällä)

Käytä vain

find filename 

olisi nopeaa, koska se vain palauttaisi filename tai filename jos se on hakemisto, tai virhe, jos nimeä ei ollut olemassa olevassa hakemistossa. Se on erittäin nopea toiminta, samanlainen kuin ls filename (mutta rekursiivinen, jos filename on hakemisto).

kontrasti,

find | grep filename 

antaisi find luoda luettelon kaikista nimistä nykyinen hakemisto ja sen alapuolella, joka grep sitten suodatettaisiin. Tämä olisi tietysti paljon hitaampi operaatio.

Oletan, että mikä oli oikeastaan tarkoitettu oli

find . -type f -name "filename" 

Tämä etsii filename tavallisen tiedoston nimellä missä tahansa nykyinen hakemisto tai sen alapuolella.

Tämä on yhtä nopeaa (tai verrattain nopeaa) kuin find | grep filename, mutta grep ratkaisu sovittaa filename kunkin löydetyn nimen täydelliseen polkuun, samalla tavalla kuin -path "*filename*" tekisi kohteen .


Sekaannus johtuu väärinkäsityksestä siitä, miten find toimii.

Apuohjelma vie useita polkuja ja palauttaa kaikki nimet näiden polkujen alle.

Voit sitten rajoita palautettuja nimiä käyttämällä erilaisia testejä, jotka voivat vaikuttaa tiedostonimeen, polkuun, aikaleimaan, tiedostokokoon, tiedostotyypiin jne.

Kun sanot

find a b c 

pyydät find luetteloimaan kaikki käytettävissä olevat nimet kolmen polun alla a, b ja c. Jos nämä sattuvat olevan nykyisen hakemiston tavallisten tiedostojen nimiä, ne palautetaan. Jos jokin niistä sattuu olemaan hakemiston nimi, se palautetaan yhdessä kaikkien muiden hakemistossa olevien nimien kanssa.

Kun teen

find . -type f -name "filename" 

Tämä luo luettelon kaikista nimistä nykyisessä hakemistossa (.) ja alla. Sitten se rajoittaa nimien tavallisten tiedostojen nimiin, ts. Ei hakemistoihin tms., -type f. Sitten nimille on vielä yksi rajoitus, joka vastaa filename käyttämällä -name "filename". Merkkijono filename voi olla tiedostonimen hämmentävä malli, kuten *.txt (muista vain lainata sitä!).

Esimerkki:

Seuraava näyttää ”löytävän” tiedoston nimeltä .profile kotihakemistostani:

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

Mutta itse asiassa se palauttaa kaikki nimet polulla .profile (nimiä on vain yksi, ja tämä on tämän tiedoston nimi).

Sitten cd ylöspäin yhden tason ja yritän uudelleen:

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

find -komento ei nyt löydä mitään polkua nimeltä .profile.

Jos saan sen tarkastelemaan nykyistä hakemistoa ja sitten rajoittamaan palautetut nimet vain .profile , se löytää se sieltä:

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

Kommentit

  • find filename palauttaisi vain filename, jos filename ei olisi tyyppiä hakemisto (tai tyypin hakemisto, mutta ei itse ollut merkintää)

Vastaus

Ei-tekninen selitys: Etsitään Jackiä joukosta on nopeampi kuin etsiä kaikkia joukosta ja eliminoida kaikki paitsi Jack.

Kommentit

  • Ongelmana on, että OP odottaa Jackin olla ainoa henkilö joukossa. Jos on, he ’ ovat onnekkaita. find jack luetteloi jack, jos se ’ sa tiedosto nimeltä jack tai kaikki hakemiston nimet, jos se ’ sa hakemisto. Se ’ on väärinkäsitys siitä, miten find toimii.

Vastaa

En ole vielä ymmärtänyt ongelmaa, mutta voin antaa lisää oivalluksia.

Kuten Kusalananda, find | grep -kutsu on selvästi nopeampi järjestelmässäni, jolla ei ole paljon järkeä. Aluksi otin jonkinlaisen puskurointiongelman; että kirjoittaminen konsolille hidastaa aikaa seuraavaan syscalliin seuraavan tiedoston nimen lukemiseen. Kirjoittaminen putkeen on erittäin nopeaa: noin 40MiB / s jopa 32-tavuisten kirjoitusten kohdalla (melko hitaassa järjestelmässäni; 300 MiB / s 1MiB: n lohkon koossa). Siksi oletin, että find voi lukea tiedostojärjestelmästä nopeammin, kun kirjoitat putkelle (tai tiedostolle), jotta tiedostopolkuja lukevat ja konsolille kirjoittavat toiminnot voisivat toimia rinnakkain ( jota find yhtenä ketjuprosessina ei voi tehdä yksin.

Se ”s find ”vika

Kahden puhelun vertailu

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

ja

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

osoittaa, että find tekee jotain uskomattoman tyhmää (mitä se sitten onkin). osoittautuu melko epäpäteväksi -name "*.txt": n suorittamisessa.

Saattaa riippua syötteen / lähdön suhteesta

Saatat ajatella, että find -name voittaa, jos kirjoitettavaa on hyvin vähän. Mutta istuu vain kiusallisemmaksi find. Se häviää, vaikka mitään kirjoitettavaa ei olisikaan vastaan 200K tiedostoja (13 M putkitietoja) kohteelle grep:

time find /usr -name lwevhewoivhol 

find voi olla yhtä nopea kuin grep, vaikka

On käynyt ilmi, että find tyhmyys name: n kanssa ei ulotu muihin testeihin. Käytä sen sijaan regexiä ja ongelma on poissa:

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

Tätä voidaan pitää virheenä. Kukaan haluaa jättää virheraportin? Oma versioni on find (GNU findutils) 4.6.0

Kommentit

  • Kuinka toistettavissa ovat ajoituksesi? Jos teit ensin -name -testin, se on saattanut olla hitaampaa, koska hakemiston sisältöä ei ole tallennettu välimuistiin. (Testattaessa -name ja -regex havaitsen, että ne vievät suunnilleen saman ajan, ainakin kun välimuistivaikutus on otettu huomioon. tietenkin se voi olla vain eri versio versiosta find …)
  • @psmears Tietenkin olen tehnyt nämä testit useita kertoja. Välimuistiongelma on mainittu jo kysymyksen kommenteissa ennen ensimmäistä vastausta. find -versioni on löydetty (GNU findutils) 4.6.0
  • Miksi on yllättävää, että -name '*.txt' -lisäys hidastuu find? Sen on tehtävä ylimääräistä työtä ja testattava jokainen tiedostonimi.
  • @Barmar Yhtäältä tämä ylimääräinen työ voidaan tehdä erittäin nopeasti. Toisaalta tämä ylimääräinen työ säästää muuta työtä. find on kirjoitettava vähemmän tietoja. Ja putkelle kirjoittaminen on paljon hitaampaa.
  • Levylle kirjoittaminen on hyvin hidasta, putkeen kirjoittaminen ei ole niin huono, se vain kopioidaan ytimen puskuriin. Huomaa, että ensimmäisessä testissä kirjoittamalla enemmän osoitteeseen /dev/null käytettiin jotenkin vähemmän järjestelmää.

Vastaus

Ilmoitus : Oletan, että tarkoitat find . -name filename (muuten etsit eri asioita; find filename etsii itse asiassa polkua nimeltä tiedostonimi , joka voi sisältää melkein yhtään tiedostoa, joten poistut todella nopeasti).


Oletetaan, että sinulla on hakemisto, jossa on viisi tuhatta tiedostoa. Useimmissa tiedostojärjestelmissä nämä tiedostot on tosiasiallisesti tallennettu puu -rakenteeseen , jonka avulla kaikki tiedostot voidaan löytää nopeasti.

Joten kun pyydät find etsimään tiedosto, jonka nimi vaatii vain tarkistuksen, find kysyy kyseiselle tiedostolle ja vain kyseiselle tiedostolle alla olevaan tiedostojärjestelmään, joka lukee hyvin vähän sivuja massamuistista. Joten jos tiedostojärjestelmä on suolansa arvoinen, tämä toiminto suoritetaan paljon nopeammin kuin läpi koko puun kaikkien tietojen hakemiseksi.

Kun pyydät tavallista find, mutta se on kuitenkin juuri sitä, mitä teet, kuljet läpi koko puun lukemalla. Jokainen. Yksittäinen. Merkintä. Suurilla hakemistoilla tämä voi olla ongelma (se on täsmälleen syy siihen, miksi useat ohjelmistot, jotka tarvitsevat tallentamaan paljon tiedostoja levylle, luovat ”hakemistopuut” kahden tai kolmen komponentin syvyyteen: tällä tavoin jokaisella yksittäisellä lehdellä on oltava vain vähemmän tiedostoja) .

Vastaus

Oletetaan, että tiedosto / john / paul / george / ringo / beatles on olemassa ja etsimäsi tiedosto kutsutaan ”kiviksi”

find / stones 

find vertaa ”beatlejä” ”kiviin” ja pudottaa sen, kun ”s” ja ”b” eivät täsmää .

find / | grep stones 

Tässä tapauksessa haku välittää ”/ john / paul / george / ringo / beatles” grepiin ja grepiin wil Minun täytyy työskennellä läpi koko polun, ennen kuin määritän, onko se ottelu.

grep tekee siis paljon enemmän työtä, minkä vuoksi se vie kauemmin

kommentit

  • Oletko antanut kokeilun?
  • Merkkijonovertailujen (äärimmäisen yksinkertainen ja halpa) kustannukset katoavat kokonaan IO: n (tai vain syscallin, jos välimuistissa) kustannukset hakemistohakuista.
  • grep ei ole ’ ta merkkijonojen vertailu, sen säännöllisen lausekkeen vertailu, mikä tarkoittaa, että sen on toimittava koko merkkijonon läpi, kunnes se joko löytää ottelun tai pääsee loppuun. Hakemistohaku on sama riippumatta siitä, mistä.
  • @Paranoid Hm, mistä löytää -versiosta puhut? Se ’ ei ilmeisesti ole mitään muuta kuin etsi I ’ m, jota tottunut debianissa.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *