2. find: failide leidmine teatud kriteeriumi alusel

find on pika ajalooga UNIX® utiliit. Selle funktsioon on uurida rekursiivselt läbi üks või rohkem kataloogi ning leida sealt failid, mis vastavad teatud kriteeriumidele. Kuigi see on väga kasulik käsk, on selle süntaks mõnevõrra keeruline ja nõuab harjutamist. Üldiselt näeb süntaks välja selline:

find [võtmed] [kataloogid] [kriteerium1] ... [kriteeriumN] [toiming]

Kui kataloogi ei anta, otsib find läbi aktiivse kataloogi. Kui kriteerium andmata jätta, arvestatakse vaikimisi kriteeriumiks “tõene”, mis tähendab, et leitakse üles kõik failid. Võtmeid, kriteeriume ja toiminguid on nii palju, et siinkohal on võimalik neist ainult mõnel peatuda. Kõigepealt mõned võtmed:

Kriteeriumiks võib olla üks või mitu atomaarset testi. Mõned kasulikumad testid:

Teste on veel päris palju, neist annab ülevaate manuaalilehekülg find(1). Testide kombineerimiseks võib kasutada üht järgnevatest võimalustest:

Lõpuks saab määrata ka toimingu, mida leitud faili(de)ga ette võtta. Sagedasemad toimingud on järgmised:

Ilmselt parim viis kõiki võtmeid ja parameetreid tundma õppida on näidete varal. Oletame, et soovime leida kõik kataloogid kataloogis /usr/share. Selleks tuleb anda käsk:

find /usr/share -type d

Oletame, et Teil on HTTP-server. Kõik Teie HTML-failid asuvad kataloogis /var/www/html, kus Te ka parasjagu viibite. Te soovite leida kõik failid, mille sisu pole muudetud kuu aja jooksul. Kuna Teil on mitmeid kirjutamisõigusega kasutajaid, kannavad osad failid laiendit html, osad aga htm. Te soovite linkida leitud failid kataloogi /var/www/obsolete. Selleks tuleb Teil anda käsk[27]:

find \( -name "*.htm" -o -name "*.html" \) -a -ctime -30 \
-exec ln {} /var/www/obsolete \;

See on suhteliselt keeruline näide, mis vajab ilmselt seletust. Kriteerium on järgmine:

\( -name "*.htm" -o -name "*.html" \) -a -ctime -30

ja teeb just seda, mis vaja: leiab kõik failid, mille nime lõpus seisab kas .htm või .html (“\( -name "*.htm" -o -name "*.html" \)”), ja (-a) mida ei ole muudetud viimase 30 päeva jooksul, mis ongi enam-vähem kuu aega (-ctime -30). Pange tähele sulge: need on siin vajalikud, sest -a seisab tehtejärjestuses kõrgemal. Kui neid ei oleks, leitkas kõik failid, mille lõpus seisab .htm, ning lisaks kõik failid, mille lõpus seisab .html ja mida ei ole muudetud viimase kuu aja jooksul, mis aga ei vastaks kuidagi meie soovile. Pange tähele ka seda, et sulud on shelli eest varjestatud: kui kirjutada \( ... \) asemel ( ... ), hakkaks shell neid oma reeglite järgi tõlgendama ning üritaks käivitada alamshellis -name "*.htm" -o -name "*.html"... Teine võimalus oleks panna sulud topelt- või ühekordsete jutumärkide vahele, aga längkriips on soovitatavam, sest sel juhul saab läbi ajada ainult ühe märgiga.

Lõpuks on siin ka käsk, mida rakendatakse kõigile failidele:

-exec ln {} /var/www/obsolete \;

Ka siin tuleb märk ; shell'i eest varjestada. Vastasel juhul tõlgendaks shell seda käsueraldajana. Kui Teil peaks see meelest minema, hoiatab find teid, et -exec on argumendita.

Viimane näide: Teil on tohutu kataloog (/shared/pildid), kus leidub kõikvõimalikke pilte. Te kasutate regulaarselt käsku touch kataloogis leiduva faili tempel aja uuendamiseks, nii et Teil on olemas aeg, millele toetuda. Te soovite nüüd leida kõik JPEG-pildid, mis on uuemad kui fail tempel, aga kuna Te olete hankinud pilte erinevatest allikatest, on neil laienditeks nii jpg, jpeg kui ka JPG ja JPEG. Samuti soovite jätta otsingul kõrvale kataloogi vanad. Lisaks soovite, et failinimekiri saadetakse Teile e-kirjana (ning Teie kasutajanimi on peter):

find /shared/pildid -cnewer     \
     /shared/pildid/tempel       \
     -a -iregex ".*\.jpe?g"     \
     -a -not -regex ".*/vanad/.*" \
       | mail peter -s "Uued pildid"

Selline käsk on mõistagi tülikas, kui Te peate iga kord kogu joru käsitsi kirja panema - ja Teil läheb seda sageli vaja. Sellise probleemi lihtsaks lahenduseks on lasta käsul perioodiliselt tööle hakata cron-deemoni abil, millest tuleb juttu järgmises osas.



[27] Arvestage, et toodud näite korral on vajalik, et /var/www ja /var/www/obsolete asuksid samas failisüsteemis!