Mustand: sisu ei ole veel tehniliselt ega keeleliselt täielikult kontrollitud ega toimetatud.

Peatüki vaade

Linux/Unix/macOS käsurea kiirõpik

Praegu loed peatükki `find` ja `xargs` ohutumalt, mis kuulub osasse Osa IV: Tekst, otsing ja automatiseerimine.

find ja xargs ohutumalt

Selles peatükis vaatame, kuidas kasutada find-i ja xargs-i nii, et tühikud ja keerulised failinimed ei lõhuks tulemust ära.

Loogika

find leiab teed.

xargs annab need teed järgmisele käsule edasi.

Probleem tekib siis, kui failinimedes on:

  • tühikud
  • tabulaatorid
  • reavahetused

Kui kasutada naiivset kuju, siis võib üks failinimi laguneda mitmeks tükiks. Sellepärast on oluline paar:

  • find ... -print0
  • xargs -0

Kiirspikker

  • find . -type f leiab failid
  • find . -name '*.txt' leiab nime järgi
  • find ... -print0 väljastab nullmärgiga eraldatud tulemused
  • xargs -0 loeb nullmärgiga eraldatud sisendi õigesti sisse
  • find ... -exec käsk {} + on sageli lihtne alternatiiv xargs-ile

Käivita need käsud


find . -type f -name '*.txt'
find . -type f -name '*.txt' -print0 | xargs -0 wc -l
find . -type f -name '*.log' -exec ls -lh {} +

Kui tahad näha just keeruliste nimede loogikat, tee väike näide:


mkdir -p find-naide
cd find-naide
touch 'üks fail.txt' 'teine fail.txt'
find . -type f -name '*.txt' -print0 | xargs -0 ls -l

Miks -print0 ja -0 tähtsad on

Vaikimisi eraldatakse käsurea tekst sageli tühikute ja reavahetuste järgi. See tähendab, et fail nimega:


minu fail.txt

võib naiivses töövoos käituda nagu kaks eri sõna.

Selle vältimiseks:

  • find -print0 eraldab tulemused nullmärgiga
  • xargs -0 loeb just seda vormi

See on praktiline “ohutu vaikevariant”, kui liigud find-ist järgmise käsuni.

xargs või -exec?

Mõlemad on kasulikud.

Näide xargs-iga:


find . -type f -name '*.txt' -print0 | xargs -0 wc -l

Näide -exec-iga:


find . -type f -name '*.txt' -exec wc -l {} +

Rusikareegel:

  • kui tahad lihtsat ja ohutut kuju, siis -exec ... + on sageli väga hea
  • kui tahad teadlikult ehitada torupõhist töövoogu, siis -print0 | xargs -0 on tugev valik

xargs vs while read

On veel üks väga kasulik kuju:


find data -type f -name '*.txt' -print0 |
while IFS= read -r -d '' fail; do
  wc -l "$fail"
done

Selle loogika on:

  • find -print0 annab failinimed ohutult edasi
  • read -r -d '' loeb ühe nullmärgiga eraldatud faili korraga
  • tsüklis saad iga faili kohta teha rohkem kui ühe sammu

xargs on väga hea siis, kui:

  • tahad ühe käsu kiiresti paljudele failidele anda

while read on eriti hea siis, kui:

  • tahad iga faili kohta teha väikese loogika
  • vajad tsüklit, tingimust või mitut käsku järjest

Näiteks:


find data -type f -name '*.txt' -print0 |
while IFS= read -r -d '' fail; do
  echo "Töötlen: $fail"
  head -n 1 "$fail"
done

Väldi pimesi hävitavaid käske

find ja xargs lähevad eriti ohtlikuks siis, kui lõppu pannakse:

  • rm
  • chmod
  • mv

Seetõttu tasub alati enne teha kuivem kontroll:


find . -type f -name '*.log'

ja alles siis panna lõppu päris tegevus.

Veel parem on alustada mittelahutava käsuga nagu:


find . -type f -name '*.log' -print0 | xargs -0 ls -lh

Tüüpilised kasutused

  • leia kõik kindla laiendiga failid
  • anna need failid edasi wc, grep, ls või mõnele skriptile
  • väldi failinimede lõhkumist tühikute peal

See peatükk seostub hästi teemadega Teksti otsimine: grep ja sugulased ja Esimene shelliskript.

Päris näide: loenda kõik data/ tekstifailid kokku

Repo data/ kaust on hea turvaline koht find-i harjutamiseks.


find data -type f -name '*.txt' -print0 | xargs -0 wc -l

Siin:

  • find leiab kõik .txt failid
  • -print0 eraldab need ohutult
  • xargs -0 wc -l annab igale failile reaarvu

See on hea näide, sest siin ei ole vaja midagi kustutada ega muuta, ainult vaadata.

Päris näide: keeruliste nimedega failid

Kui tahad näha, miks -print0 ja -0 on päriselt vajalikud, tee selline väike töökaust:


mkdir -p otsi-naide/'Tallinn andmed'
cp data/sample-words.txt 'otsi-naide/Tallinn andmed/sonad 1.txt'
cp data/sample-text.txt 'otsi-naide/Tallinn andmed/tekst 2.txt'
find otsi-naide -type f -name '*.txt' -print0 | xargs -0 ls -lh

Selle töövoo mõte on:

  • failinimedes on tühikud
  • naiivne xargs võiks need lõhkuda
  • -print0 | xargs -0 hoiab need tervikuna koos

Päris näide: ohutu alternatiiv -exec

Sama töö saab sageli teha ka ilma xargs-ita:


find otsi-naide -type f -name '*.txt' -exec wc -l {} +

See on sageli kõige lihtsam kuju siis, kui:

  • tahad ühe käsu kõikidele tulemustele rakendada
  • ei taha mõelda sisendi eraldamisele eraldi torus

Päris näide: leia logifail ja vaata selle suurust


find data -type f -name '*.log' -exec ls -lh {} +

See on väike, aga päris praktiline muster:

  • leia failid
  • ära hävita midagi
  • vaata enne suurust või arvu

Just nii peakski find-iga töötamine algama.

Minitest

  1. Loo vähemalt üks fail, mille nimes on tühik.
  2. Leia see fail find-iga.
  3. Näita seda faili ls -l abil läbi töövoo -print0 | xargs -0.
  4. Seleta ühe lausega, miks -print0 ja -0 koos käivad.
  5. Loenda data/ kausta tekstifailide read käsuga find ... -print0 | xargs -0 wc -l.
  6. Tee sama töövoog uuesti kujul while IFS= read -r -d '' fail; do ...; done.