| Sokat gondolkoztunk, hogy hogyan tudnnk bemutatni, mit is tud a parancssor. Amint azt lthatttok, sikerlt olyan sokat gondolkoznunk ezen a problmn, hogy ki is maradt egy cikk. Vgl az a dnts szletett: bemutatunk egy "llatorvosi l" jelleg scriptet, ami ugyan nem a legelegnsabb mdon, de nagyon sok opcit s hasznos funkcit mutat vgig.
Az alapproblma:
Van egy csom mp3 fjlunk, s ezen fjlok nevben szkz karakter tallhat. Nos, ezt szeretnnk kigyomllni, mert a szkz egy problms karakter s kicserlnnk mindenhol ktjell. Magyarn: Gyozike - Elso albuma - elso szam.mp3 fjlbl szeretnnk Gyozike-Elso-albuma-elso-szam.mp3 fjlt csinlni. Ezt megtehetnnk egyesvel is, mondjuk nyitunk egy fjlkezelt, majd tnevezs, majd ismt egy fjl, majd....
Lthatan ez igen problms. Itt jn be a shell hasznossga, s a shellscript: automatizljuk ezt a folyamatot!
Els lps
Vizsgljuk meg ezt a problmt elszr "egyszeren", hiszen nagyon messzire el lehet jutni egy parancs segtsgvel is!
Miutn belelptnk a knyvtrba (cd /ahol/vannak/a/fajlok ) elszr is listzzuk ki annak tartalmt!
A manulok Az egyes parancsok elsajttsra rendelkeznek igen j dokumentcival. A manul a "man parancsnv" parancs kiadsval rhet el. Ha nem rtjk itt mit mirt csinlunk, vegyk el a parancs manuljt! |
bbt@bbt:~$ cd /zene/living magic (<-belpnk a neknk kell knyvtrba) bbt@bbt:/zene/living magic$ ls (<- kilistzzuk) living magic.doc Trilok Gurtu - Living Magic - 01 - Baba.mp3 Trilok Gurtu - Living Magic - 02 - Living Magic.mp3 Trilok Gurtu - Living Magic - 03 - Once I Wished a Tree Upside Down....mp3 Trilok Gurtu - Living Magic - 04 - Transition.mp3 Trilok Gurtu - Living Magic - 05 - From Scratch.mp3 Trilok Gurtu - Living Magic - 06 - Tac, et Demi.mp3 Trilok Gurtu - Living Magic - 07 - TMNOK.mp3
Amint lthat, elszr is el kne rnnk, hogy csak az mp3 fjlokat rassuk ki. Mit tehetnk? Kt megolds is addik hirtelen: a legjobb az ls parancs korrekt hasznlata:
bbt@bbt:/zene/living magic$ ls *.mp3 Trilok Gurtu - Living Magic - 01 - Baba.mp3 Trilok Gurtu - Living Magic - 02 - Living Magic.mp3 Trilok Gurtu - Living Magic - 03 - Once I Wished a Tree Upside Down....mp3 Trilok Gurtu - Living Magic - 04 - Transition.mp3 Trilok Gurtu - Living Magic - 05 - From Scratch.mp3 Trilok Gurtu - Living Magic - 06 - Tac, et Demi.mp3 Trilok Gurtu - Living Magic - 07 - TMNOK.mp3
A msik ugyanezt az eredmnyt adja: ls | fgrep '.mp3'
Mi is trtnik? Elszr kiadunk egy listzst, ami kirat mindent, majd a "|" jel segtsgvel ebbl egy "csvet" (pipe) kpeznk, magyarn a parancs kimenett tadjuk a kvetkez parancsnak, mint bemenet. A msodik parancs a fgrep, de esetnkben llhatna ott grep is: ez a parancs szortroz, csak azokat a sorokat ratja ki, melyekben a ".mp3" karakterlnc szerepel. Hogy mirt van idzjelben a .mp3? A shell nhny karaktert specilisan kezel. Bizonyos helyzetekben ilyen a pont is. Idzjelben azonban elveszti eredeti jelentst. (Ez a magyarzat tvolrl sem teljes, azonban ha komolyan belemennnk, abbl kln cikk lenne...)
Ebben az esetben viszonylag egyszeren is megoldhat a feladat, hiszen ha csak kivgjuk a szkzt, az is megoldst nyjthatna, s pont erre val a tr parancs: a tr -d ' ' egyszeren kivgja a szkzket. A tr parancs bemenetnek pedig egyszeren meg kell adni az elbbi parancs kimenett:
bbt@bbt:/zene/living magic$ ls | fgrep '.mp3' | tr -d ' ' TrilokGurtu-LivingMagic-01-Baba.mp3 TrilokGurtu-LivingMagic-02-LivingMagic.mp3 TrilokGurtu-LivingMagic-03-OnceIWishedaTreeUpsideDown....mp3 TrilokGurtu-LivingMagic-04-Transition.mp3 TrilokGurtu-LivingMagic-05-FromScratch.mp3 TrilokGurtu-LivingMagic-06-Tac,etDemi.mp3 TrilokGurtu-LivingMagic-07-TMNOK.mp3
Siker! Azonban mi ugye nem teljesen ezt szeretnnk... Ok, akkor kicsit msra lesz szksgnk:
bbt@bbt:/zene/living magic$ ls | fgrep '.mp3' | tr -s ' -' '-' Trilok-Gurtu-Living-Magic-01-Baba.mp3 Trilok-Gurtu-Living-Magic-02-Living-Magic.mp3 Trilok-Gurtu-Living-Magic-03-Once-I-Wished-a-Tree-Upside-Down....mp3 Trilok-Gurtu-Living-Magic-04-Transition.mp3 Trilok-Gurtu-Living-Magic-05-From-Scratch.mp3 Trilok-Gurtu-Living-Magic-06-Tac,-et-Demi.mp3 Trilok-Gurtu-Living-Magic-07-TMNOK.mp3
Amint lthat, a tr -s ' -' '-' parancs hatsra a "-" s a " " karaktereket kicserlte "-" karakterre, de ahol tbb llt volna egyms utn, csak egyet hagyott meg. Ksz is vagyunk. Vagy nem? Kisebb szpsghibja a dolognak, hogy a fjlok nevei nem vltoztak meg, mi csak az ls kimenetvel jtszadoztunk el. Azonban igen j ton haladunk a megoldshoz!
Teht van egy parancsunk, amit ha meg tudunk adni az "mv" (fjl mozgats, tnevezs) parancsnak, hogy hajtsa vge, mr gyznnk is. Rviden felvzolnnk erre a feladatra megoldsi javaslatunkat: listzzuk ki a fjlokat, a listt pakoljuk be egy fjlba, majd a fjl sorait egyesvel felolvasva nevezzk t ket. Nem is tnik nehznek...
Vgjunk bele!
Az eleje egyszer (felttelezve, hogy mr belelpnk a knyvtrba): ls '.mp3' > lista A parancs hatsra ltrejn egy "lista" nev fjl a knyvtrban, mely soronknt tartalmazza a knyvtrban tallhat fjlok neveit. A ">" szintn egy tirnyts, az ls eredetileg a szabvnyos kimenetre ratta volna a listt, mi azonban ehelyett egy fjlt adtunk meg neki.
tirnytsok Nagyon hasznos s gyakran haszlt funkci az tirnyts, mindenkpp nzznk utna hogyan is mkdnek pontosan!
Ciklusok Termszetesen shell esetben is van for ciklus, stb. Szintn rdemes utnaolvasni, ha mshol nem: man bash | Szksgnk lesz egy ciklusra, hogy a mveletet annyiszor hajthassuk vgre, ahny fjl van a knyvtrban (vagy ahny sora van a lista fjlnak... ), erre egy while ciklust fogunk hasznlni, s itt lpjk t azt a hatrt, ahol mr bonyolult lenne a parancsokat konzolon kiadni, s rdemes egy fjlba dolgozni. (Megjegyeznnk: nem szksgszer, kis odafigyelssel nem kell fjl, a cikk vgn megmutatnnk hogy hogyan lehet ezt a parancsot "egybe" kiadni.) Szintn a teljessg ignye nlkl: a while ciklus addig fut, amg aztn a megadott felttel igaz. Ez a felttel akrmilyen parancs lehet, a lnyeg, hogy a visszar rtke 0 legyen, magyarn rendben lefusson. Esetnkben ez a "test" parancs lesz (ne tvesszen meg senkit: a "test" parancs megegyezik a "[" paranccsal, mgha ez nem is ltszik rajta), s kt vltozt hasonltunk ssze: a cikluson bell az egyiket lptetjk felfele, a msik kezdrtknek egy megadjuk a "lista" fjl sorainak szmt:
#!/bin/bash ls | fgrep '.mp3' > lista
i=$(wc -l lista | cut -d ' ' -f1) j=1 while [ "$j" -le "$i" ] do #itt lesz majd a parancs j=$(( $j + 1 )) done
rtelmezzk kicsit:
- Az els sor egy megjegyzs, bash s egyb POSIX kompatibilis shellek esetben a "#" jel utni rszrl nem vesz tudomst a parancsrtelmez, kivve az els sort. Itt a fent szintaktikval megadott sor akkor kerl rtelmezsre, ha futtatni akarjuk a fjlt, ebben az esetben a shell megnzi, hogy milyen futtatkrnyezetben kell indtania. Esetnkben ez a bash parancsrtelmez, de ez lehetne egy Perl script is, akkor ott "#!/usr/bin/perl" llna.
- A msodik sort ismerjk,
- a kvetkezt mg nem: az i vltozba helyezzk be a "wc -l lista | cut -d ' ' -f1" parancs eredmnyt. Ez a parancs viszonylag egyszer:
wc -l lista - megszmolja a lista fjl sorainak szmt. Azonban a kimenete gy nz ki:
bbt@bbt:/zene/living magic$ wc -l lista 7 lista
s ebbl neknk le kne vgni az els oszlopot, amennyiben az oszlopokat szkz vlasztja el:
bbt@bbt:/zene/living magic$ wc -l lista | cut -d ' ' -f1 7 Esetnkben j lett volna, ha csak az els karaktert vgjuk le, de ha 9-nl tbb mp3 van a knyvtrban, mr nem mkdne, ezrt ez jobb megoldsnak tnik.
- A script kvetkez sora kimondja, hogy a j vltoz rtke 1, majd kezd a ciklus:
- Amg a j vltoz kisebb vagy egyenl az i vltoznl, addig hajtsa vgre az albbi mveleteket. Ide ugye mg nem raktunk semmit, leszmtva a j inkrementlst.
Amint lthat, elegnsan tlpjk azokat krdseket, hogy mirt ilyen a szintaktika, mirt vannak idzjelben a vltozk. Egyedl annyit emelnnk ki, hogy ha egy vltoz rtkre van szksgnk, arra a $vltoz mdon hivatkozhatunk.
Idzjelek Ms jelentse van az egyszer s a dupla idzjelnek a shellben, de ismtelen helyszke okn nem rszleteznnk ki pontosan. Egyszerstve: az egyszeres minden specilis dolgot megszntet, s tisztn szvegknt rtelmezi abenne lv dolgokat a shell, amg a dupla idzjelben pldul a $i vltozatlanul egy vltozhivatkozs marad. Teht: '$i' - a $i karakterek. "$i" - az i vltoz rtke |
De mi kerl a parancsba?
Vegyk el mg egy pillanatra az i-nek rtkad sort:
i=$(wc -l lista | cut -d ' ' -f1)
Van itt egy rdekes, s hasznos funkci: a parancskihelyettests. Az i vltoz rtke egyenl lesz a $( ) rszben lv parancs(ok) kimenetvel. Magyarn, ahogy lttuk a wc -l | cut -d ' ' -f1 parancs eredmnye 7 lesz. Esetnkben i rtke is 7 lesz, s nem pedig az a parancs, amit belertunk. Ha ez szerepelt volna ott: i='wc -l lista | cut -d " '" f1', akkor i rtke wc -l lista | cut -d " '" f1 lett volna, szvegknt rtelmezve. Amint lthat a shellt klnsebben nem rdekli, hogy szm vagy bet szerepel a vltozban, egszen addig, amg olyan mveletet nem akarunk vgrehajtani vele, ami ezt felttelezi. (pl. test).
Nos, hasznljuk ki ezt a tulajdonsgot (mrhogy a parancskihelyettestst)!
Elvi skon: mv $(egy sort kiemelnk a fjlbl) $(tnevezs)
Elszr az els fele:
$(head -"$j" lista | tail -1)
A head parancs megmutatja a lista fjl els nhny sort. Azt, hogy mennyit, azt a "-" kapcsol utn adjuk meg neki. Mivel a $j egy szm, elszr "head -1" lesz belle , majd "head -2" stb. Ez azt jelenti, hogy elszr az els sort rja ki, utna az els kettt, stb...
A tail -1 paranccsal levgjuk a kimenet utols sort. Magyarn elszr az els sor a kimenet, majd a msodik, stb.
s mivel a lista fjl tartalma a knyvtrban tallhat fjlok nevei soronknt, ezzel meg is lennnk: a cikluson bell minden futskor egy sort r ki, elszr az elst, utna a msodikat, stb. Ezek rendre a neknk kell fjlok nevei.
A msodik rsze a parancsnak szintn ksz van, hiszen az elbbi parancsot kell "lekezelnnk" a cikk elejn jelzett mdon:
$(head -"$j" lista | tail -1 | tr -s ' -' '-')
Ugye lthat: kivgjuk az egy sort, majd a korbban trgyalt mdon azt a sort megadva a tr parancsnak, kicserljk amit ki kell.
Ksz is vagyunk:
mv "$(head -"$j" lista | tail -1)" "$(head -"$j" lista | tail -1 | tr -s ' -' '-')"
Mr csak be kell helyeznnk a scriptbe, aminek vgleges vltozata gy nz ki:
#!/bin/bash ls | fgrep '.mp3' > lista
i=$(wc -l lista | cut -d ' ' -f1) j=1 while [ "$j" -le "$i" ] do mv "$(head -"$j" lista | tail -1)" "$(head -"$j" lista | tail -1 | tr -s ' -' '-')" j=$(( $j + 1 )) done
Ezt bemsoljuk egy script nev fjlba, majd lefuttatjuk. Ezt ktflekpp tehetjk meg: vagy egy "chmod +x script" paranccsal futtathatv tesszk s "./script" mdon indtjuk, vagy a "bash script" parancs kiadsval is futtathatjuk.
A valsgban mi fog trtnni? Els futskor a parancs megkapja az els fjlt s kihelyettestdik, magyarn lefut ez a parancs:
mv "Trilok Gurtu - Living Magic - 01 - Baba.mp3" Trilok-Gurtu-Living-Magic-01-Baba.mp3
(Az idzjel azrt kell, hogy a shell egy fjl nevnek kezelje, mivel a szkzt gy rtelmezi, hogy addig tartott az els fjlnv.)
Futtassuk le!
Eltte s mgtte kilistzzuk a fjl tartalmt, hogy ltszdjon a hats, teht:
bbt@bbt:/zene/living magic$ ls lista living magic_mp3.doc script Trilok Gurtu - Living Magic - 01 - Baba.mp3 Trilok Gurtu - Living Magic - 02 - Living Magic.mp3 Trilok Gurtu - Living Magic - 03 - Once I Wished a Tree Upside Down....mp3 Trilok Gurtu - Living Magic - 04 - Transition.mp3 Trilok Gurtu - Living Magic - 05 - From Scratch.mp3 Trilok Gurtu - Living Magic - 06 - Tac, et Demi.mp3 Trilok Gurtu - Living Magic - 07 - TMNOK.mp3 bbt@bbt:/zene/living magic$ bash script bbt@bbt:/zene/living magic$ ls lista living magic_mp3.doc script Trilok-Gurtu-Living-Magic-01-Baba.mp3 Trilok-Gurtu-Living-Magic-02-Living-Magic.mp3 Trilok-Gurtu-Living-Magic-03-Once-I-Wished-a-Tree-Upside-Down....mp3 Trilok-Gurtu-Living-Magic-04-Transition.mp3 Trilok-Gurtu-Living-Magic-05-From-Scratch.mp3 Trilok-Gurtu-Living-Magic-06-Tac,-et-Demi.mp3 Trilok-Gurtu-Living-Magic-07-TMNOK.mp3
Hm. gy ltszik kszen is vagyunk. Termszetesen ez egy igen kezdetleges script, szmos mdon lehetne mg tkletesteni, s tbb helyen nem a leghatkonyabb megoldst vlasztottuk, de valsznleg igen jl ttekinthet az eredmny, s szmos hasznos tulajdonsgt be tudtuk mutatni egy Unix/Linux shellnek. Esetnkben a Bash parancsrtelmezt hasznltuk, de ez a script j esllyel elfutna ms parancsrtelmezk alatt is.
Emltettk, ez kiadhat parancssorban is, egy parancsknt. Akkor gy nzne ki a script:
ls | fgrep '.mp3' > lista ; i=$(wc -l lista | cut -d ' ' -f1) ; j=1 ; while [ "$j" -le "$i" ]; do; mv "$(head -"$j" lista | tail -1)" "$(head -"$j" lista | tail -1 | tr -s ' -' '-')" ; j=$(( $j + 1 ));done
Vgl is semmi nem ms benne, csak a sortrsek helyn pontosvessz ll...
Amire gyeljnk:
Shell scripteknl igen fontos a kompatibilitsi krds. Az egyes parancsok eltr rendszereken ms-ms kimenetet produklhatnak, ami igen komolyan megneheztheti dolgunkat, s nem vrt problmkat vethet fel. Ezen kvl rdemes gyelni a helyes parancshasznlatra. rdemes tbb id tlteni a manulok olvasgatsval, mert ha hrom "|" segtsgvel oldunk meg egy feladatot, az minden esetben sokkal lassabb futs eredmnyez, mint egy parancs egy helyesen megvlasztott kapcsolval. (pl.: ls | fgrep '.mp3' helyett ls *.mp3)
Ez a cikk csak a felsznt kapargatja, s szmos dolog okt -helyszke miatt- nem rszleteztnk kell mrtkben. Aki shell scriptekkel akar foglalkozni btran tmadja meg az Internetet tovbbi lersokat keresve, s nzzen utna, hogy mkdnek az egyes eszkzk (pl. ciklus, mi az a joker karakter, stb.), mi inkbb csak kedvet prbltunk csinlni hozz.
| |