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 kuintime find "$HOME" | grep -F '.profile'
. (17s vs. 12s). - @JenniferAnderson juoksin molemmat toistuvasti. 17 ja 12 sekuntia ovat keskiarvoja. Ja kyllä,
grep
-vaihtoehto sopii mihin tahansafind
-tulokseen, kun taas vastaavuusfind -name
sopisi vain tarkalleen (tässä tapauksessa). - Kyllä,
find filename
olisi nopeaa . Oletin, että tämä oli kirjoitusvirhe ja että OP tarkoittifind -name filename
. Kohdassafind filename
vainfilename
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
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
luetteloijack
, jos se ’ sa tiedosto nimeltäjack
tai kaikki hakemiston nimet, jos se ’ sa hakemisto. Se ’ on väärinkäsitys siitä, mitenfind
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 versiostafind
…) - @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 hidastuufind
? 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.
find filename
palauttaisi vainfilename
, josfilename
ei olisi tyyppiä hakemisto (tai tyypin hakemisto, mutta ei itse ollut merkintää)