Pyrero' s Home Page!
Mindenféle
     
Linuxos oldalak
     
Hírek
     
Bejelentkezés
Felhasználónév:

Jelszó:
SúgóSúgó
Regisztráció
Elfelejtettem a jelszót
     
G-mail Belépés
Felhasználónév:
Jelszó:
  SúgóSúgó

Új postafiók regisztrációja
     
Mennyien voltatok?
Indulás: 2005-02-27
     
Írjunk scriptet...példa

Sokat gondolkoztunk, hogy hogyan tudnánk bemutatni, mit is tud a parancssor. Amint azt láthattátok, sikerült olyan sokat gondolkoznunk ezen a problémán, hogy ki is maradt egy cikk. Végül az a döntés született: bemutatunk egy "állatorvosi ló" jellegű scriptet, ami ugyan nem a legelegánsabb módon, de nagyon sok opciót és hasznos funkciót mutat végig.

Az alapprobléma:

Van egy csomó mp3 fájlunk, és ezen fájlok nevében szóköz karakter található. Nos, ezt szeretnénk kigyomlálni, mert a szóköz egy problémás karakter és kicserélnénk mindenhol kötőjellé. Magyarán: Gyozike - Elso albuma - elso szam.mp3 fájlból szeretnénk Gyozike-Elso-albuma-elso-szam.mp3 fájlt csinálni.
Ezt megtehetnénk egyesével is, mondjuk nyitunk egy fájlkezelőt, majd átnevezés, majd ismét egy fájl, majd....

Láthatóan ez igen problémás. Itt jön be a shell hasznossága, és a shellscript: automatizáljuk ezt a folyamatot!

Első lépés

Vizsgáljuk meg ezt a problémát először "egyszerűen", hiszen nagyon messzire el lehet jutni egy parancs segítségével is!

Miután beleléptünk a könyvtárba (cd /ahol/vannak/a/fajlok ) először is listázzuk ki annak tartalmát!

A manuálok
Az egyes parancsok elsajátítására rendelkeznek igen jó dokumentációval. A manuál a "man parancsnév" parancs kiadásával érhető el. Ha nem értjük itt mit miért csinálunk, vegyük elő a  parancs manuálját!


bbt@bbt:~$ cd /zene/living magic      (<-belépünk a nekünk kellő könyvtárba)
bbt@bbt:/zene/living magic$ ls          (<- kilistázzuk)
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 látható, először is el kéne érnünk, hogy csak az mp3 fájlokat írassuk ki. Mit tehetünk? Két megoldás is adódik hirtelen: a legjobb az ls parancs korrekt használata:

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 másik ugyanezt az eredményt adja: ls | fgrep '.mp3'

Mi is történik? Először kiadunk egy listázást, ami kiírat mindent, majd a "|" jel segítségével ebből egy "csövet" (pipe) képezünk, magyarán a parancs kimenetét átadjuk a következő parancsnak, mint bemenet. A második parancs a fgrep, de esetünkben állhatna ott grep is: ez a parancs szortíroz, csak azokat a sorokat íratja ki, melyekben a ".mp3" karakterlánc szerepel. Hogy miért van idézőjelben a .mp3? A shell néhány karaktert speciálisan kezel. Bizonyos helyzetekben ilyen a pont is. Idézőjelben azonban elveszíti eredeti jelentését. (Ez a magyarázat távolról sem teljes, azonban ha komolyan belemennénk, abból külön cikk lenne...)

Ebben az esetben viszonylag egyszerűen is megoldható a feladat, hiszen ha csak kivágjuk a szóközt, az is megoldást nyújthatna, és pont erre való a tr parancs: a tr -d '  ' egyszerűen kivágja a szóközöket. A tr parancs bemenetének pedig egyszerűen meg kell adni az előbbi parancs kimenetét:

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 szeretnénk... Oké, akkor kicsit másra lesz szükségünk:

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 látható, a tr -s ' -' '-' parancs hatására a "-" és a " " karaktereket kicserélte "-" karakterre, de ahol több állt volna egymás után, csak egyet hagyott meg.
Kész is vagyunk. Vagy nem? Kisebb szépséghibája a dolognak, hogy a fájlok nevei nem változtak meg, mi csak az ls kimenetével játszadoztunk el. Azonban igen jó úton haladunk a megoldáshoz!

Tehát van egy parancsunk,
amit ha meg tudunk adni az "mv" (fájl mozgatás, átnevezés) parancsnak, hogy hajtsa vége, már győznénk is.
Röviden felvázolnánk erre a feladatra megoldási javaslatunkat: listázzuk ki a fájlokat, a listát pakoljuk be egy fájlba, majd a fájl sorait egyesével felolvasva nevezzük át őket. Nem is tűnik nehéznek...

Vágjunk bele!

Az eleje egyszerű (feltételezve, hogy már belelépünk a könyvtárba): ls '.mp3' > lista
A parancs hatására létrejön egy "lista" nevű fájl a könyvtárban, mely soronként tartalmazza a könyvtárban található fájlok neveit. A ">" szintén egy átirányítás, az ls eredetileg a szabványos kimenetre íratta volna a listát, mi azonban ehelyett egy fájlt adtunk meg neki.

Átirányítások
Nagyon hasznos és gyakran haszált funkció az átirányítás, mindenképp nézzünk utána hogyan is működnek pontosan!

Ciklusok
Természetesen shell esetében is van for ciklus, stb. Szintén érdemes utánaolvasni, ha máshol nem:
man bash
Szükségünk lesz egy ciklusra, hogy a műveletet annyiszor hajthassuk végre, ahány fájl van a könyvtárban (vagy ahány sora van a lista fájlnak... ), erre egy while ciklust fogunk használni, és itt lépjük át azt a határt, ahol már bonyolult lenne a parancsokat konzolon kiadni, és érdemes egy fájlba dolgozni. (Megjegyeznénk: nem szükségszerű, kis odafigyeléssel nem kell fájl, a cikk végén megmutatnánk hogy hogyan lehet ezt a parancsot "egybe" kiadni.)
Szintén a teljesség igénye nélkül: a while ciklus addig fut, amíg aztán a megadott feltétel igaz. Ez a feltétel akármilyen parancs lehet, a lényeg, hogy a visszaérő értéke 0 legyen, magyarán rendben lefusson. Esetünkben ez a "test" parancs lesz (ne tévesszen meg senkit: a "test" parancs megegyezik a "[" paranccsal, mégha ez nem is látszik rajta), és két változót hasonlítunk össze: a cikluson belül az egyiket léptetjük felfele, a másik kezdőértékének egy megadjuk a "lista" fájl sorainak számát:

#!/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

Értelmezzük kicsit:
  • Az első sor egy  megjegyzés, bash és egyéb POSIX kompatibilis shellek esetében a "#" jel utáni részről nem vesz tudomást a parancsértelmező, kivéve az első sort. Itt a fent szintaktikával megadott sor akkor kerül értelmezésre, ha futtatni akarjuk a fájlt, ebben az esetben a shell megnézi, hogy milyen futtatókörnyezetben kell indítania. Esetünkben ez a bash parancsértelmező, de ez lehetne egy Perl script is, akkor ott "#!/usr/bin/perl" állna.
  • A második sort ismerjük,
  • a következőt még nem: az i változóba helyezzük be a "wc -l lista | cut -d ' ' -f1" parancs eredményét. Ez a parancs viszonylag egyszerű:
    wc -l lista - megszámolja a lista fájl sorainak számát. Azonban a kimenete így néz ki:

    bbt@bbt:/zene/living magic$ wc -l lista
    7 lista

    és ebből nekünk le kéne vágni az első oszlopot, amennyiben az oszlopokat szóköz választja el:

    bbt@bbt:/zene/living magic$ wc -l lista | cut -d ' ' -f1
    7
    Esetünkben jó lett volna, ha csak az első karaktert vágjuk le, de ha 9-nél több mp3 van a könyvtárban, már nem működne, ezért ez jobb megoldásnak tűnik.
  • A script következő sora kimondja, hogy a j változó értéke 1, majd kezd a ciklus:
  • Amíg a j változó kisebb vagy egyenlő az i változónál, addig hajtsa végre az alábbi műveleteket. Ide ugye még nem raktunk semmit, leszámítva a j inkrementálását.

Amint látható, elegánsan átlépjük azokat  kérdéseket, hogy miért ilyen a szintaktika, miért vannak idézőjelben a változók. Egyedül annyit emelnénk ki, hogy ha egy változó értékére van szükségünk, arra a $változó módon hivatkozhatunk.

Idézőjelek
Más jelentése van az egyszerű és a dupla idézőjelnek a shellben, de ismételen helyszűke okán nem részleteznénk ki pontosan.
Egyszerűsítve: az egyszeres minden speciális dolgot megszüntet, és tisztán szövegként értelmezi abenne lévő dolgokat a  shell, amíg a dupla idézőjelben például a $i változatlanul egy változóhivatkozás marad. Tehát:
'$i'  - a $i  karakterek.
"$i" - az i változó értéke

De mi kerül a parancsba?

Vegyük elő még egy pillanatra az i-nek értékadó sort:

i=$(wc -l lista | cut -d '  ' -f1)

Van itt egy érdekes, és hasznos funkció: a parancskihelyettesítés. Az i változó értéke egyenlő lesz a $( ) részben lévő parancs(ok) kimenetével. Magyarán, ahogy láttuk a wc -l | cut -d '  ' -f1 parancs eredménye 7 lesz. Esetünkben i értéke is 7 lesz, és nem pedig az a parancs, amit beleírtunk. Ha ez szerepelt volna ott: i='wc -l lista | cut -d "  '" f1', akkor i értéke wc -l lista | cut -d "  '" f1 lett volna, szövegként értelmezve. Amint látható a shellt különösebben nem érdekli, hogy szám vagy betű szerepel a változóban, egészen addig, amíg olyan műveletet nem akarunk végrehajtani vele, ami ezt feltételezi. (pl. test).

Nos, használjuk ki ezt a tulajdonságot (márhogy a parancskihelyettesítést)!

Elvi síkon:
mv $(egy sort kiemelünk a fájlból) $(átnevezés)

Először az első fele:

$(head -"$j" lista | tail -1)

A head parancs megmutatja a lista fájl első néhány sorát. Azt, hogy mennyit, azt a "-" kapcsoló után adjuk meg neki. Mivel a $j egy szám, először "head -1" lesz belőle , majd "head -2" stb. Ez azt jelenti, hogy először az első sort írja ki, utána az első kettőt, stb...

A tail -1 paranccsal levágjuk a kimenet utolsó sorát. Magyarán először az első sor a kimenet, majd a második, stb.

És mivel a lista fájl tartalma a könyvtárban található fájlok nevei soronként, ezzel meg is lennénk: a cikluson belül minden futáskor egy sort ír ki, először az elsőt, utána a másodikat, stb. Ezek rendre a nekünk kellő fájlok nevei.

A második része a parancsnak szintén kész van, hiszen az előbbi parancsot kell "lekezelnünk" a cikk elején jelzett módon:

$(head -"$j" lista | tail -1 | tr -s ' -' '-')

Ugye látható: kivágjuk az egy sort, majd a korábban tárgyalt módon azt a sort megadva a tr parancsnak, kicseréljük amit ki kell.

Kész is vagyunk:

mv "$(head -"$j" lista | tail -1)" "$(head -"$j" lista | tail -1 | tr -s ' -' '-')"

Már csak be kell helyeznünk a scriptbe, aminek végleges változata így néz 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 bemásoljuk egy script nevű fájlba, majd lefuttatjuk. Ezt kétféleképp tehetjük meg: vagy egy "chmod +x script" paranccsal futtathatóvá tesszük és "./script" módon indítjuk, vagy a "bash script" parancs kiadásával is futtathatjuk.

A valóságban mi fog történni? Első futáskor a parancs megkapja az első fájlt és kihelyettesítődik, magyarán lefut ez a parancs:

mv "Trilok Gurtu - Living Magic - 01 - Baba.mp3" Trilok-Gurtu-Living-Magic-01-Baba.mp3

(Az idézőjel azért kell, hogy a shell egy fájl nevének kezelje, mivel ő a szóközt úgy értelmezi, hogy addig tartott az első fájlnév.)

Futtassuk le!

Előtte és mögötte kilistázzuk a fájl tartalmát, hogy látszódjon a hatás, tehát:

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 látszik készen is vagyunk.
Természetesen ez egy igen kezdetleges script, számos módon lehetne még tökéletesíteni, és több helyen nem a leghatékonyabb megoldást választottuk, de valószínűleg igen jól áttekinthető az eredmény, és számos hasznos tulajdonságát be tudtuk mutatni egy Unix/Linux shellnek. Esetünkben a Bash parancsértelmezőt használtuk, de ez a script jó eséllyel elfutna más parancsértelmezők alatt is.

Említettük, ez kiadható parancssorban is, egy parancsként. Akkor így nézne 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

Végül is semmi nem más benne, csak a sortörések helyén pontosvessző áll...

Amire ügyeljünk:

Shell scripteknél igen fontos a kompatibilitási kérdés. Az egyes parancsok eltérő rendszereken más-más kimenetet produkálhatnak, ami igen komolyan megnehezítheti dolgunkat, és nem várt problémákat vethet fel.
Ezen kívül érdemes ügyelni a helyes parancshasználatra. Érdemes több idő tölteni a manuálok olvasgatásával, mert ha három "|" segítségével oldunk meg egy feladatot, az minden esetben sokkal lassabb futás eredményez, mint egy parancs egy helyesen megválasztott kapcsolóval. (pl.: ls | fgrep '.mp3' helyett ls *.mp3)

Ez a cikk csak a felszínt kapargatja, és számos dolog okát -helyszűke miatt- nem részleteztünk kellő mértékben. Aki shell scriptekkel akar foglalkozni bátran támadja meg az Internetet további leírásokat keresve, és nézzen utána, hogy működnek az egyes eszközök (pl. ciklus, mi az a joker karakter, stb.), mi inkább csak kedvet próbáltunk csinálni hozzá.

     
Idő/Dátum
     
Linux alapok I. rész
     
Linux alapok II. rész
     
Linux alapok III.rész
     
Linux alapok IV.rész
     
Linux alapok V.rész
     
Linux alapok VI.rész
     
Linux alapok VII.rész
     
Linux alapok VIII.rész
     
Linux alapok IX.rész
     
Linux alapok X.rész
     
Linux alapok XI.rész
     
Linux alapok XII.rész
     
Linux alapok XIII.rész
     
Linux alapok XIV.rész
     

Szeretnél egy jó receptet? Látogass el oldalamra, szeretettel várlak!    *****    Minõségi Homlokzati Hõszigetelés. Vállaljuk családi házak, lakások, nyaralók és egyéb épületek homlokzati szigetelését.    *****    Amway termék elérhetõ áron!Tudta, hogy az általános tisztítószer akár 333 felmosásra is alkalmas?Több info a weboldalon    *****    Florence Pugh magyar rajongói oldal. Ismerd meg és kövesd az angol színésznõ karrierj&#232;t!    *****    Fele királyságomat nektek adom, hisz csak rátok vár ez a mesebirodalom! - Új menüpont a Mesetárban! Nézz be te is!    *****    DMT Trip napló, versek, történetek, absztrakt agymenés:)    *****    Elindult a Játék határok nélkül blog! Részletes információ az összes adásról, melyben a magyarok játszottak + egyéb infó    *****    Florence Pugh Hungary - Ismerd meg az Oppenheimer és a Dûne 2. sztárját.    *****    Megnyílt az F-Zero Hungary! Ismerd meg a Nintendo legdinamikusabb versenyjáték-sorozatát! Folyamatosan bõvülõ tartalom.    *****    A Cheer Danshi!! nem futott nagyot, mégis érdemes egy esélyt adni neki. Olvass róla az Anime Odyssey blogban!    *****    A 1080° Avalanche egy méltatlanul figyelmen kívül hagyott játék, pedig a Nintendo egyik remekmûve. Olvass róla!    *****    Gundel Takács Gábor egy különleges könyvet adott ki, ahol kiváló sportolókkal a sport mélységébe nyerhetünk betekintést.    *****    21 napos életmódváltás program csatlakozz hozzánk még!Január 28-ig 10% kedvezménnyel plusz ajándékkal tudod megvásárolni    *****    Szeretne egy olyan általános tisztítószert ami 333 felmosásra is elegendõ? Szeretne ha csíkmentes lenne? Részletek itt!!    *****    Új játék érkezett a Mesetárba! Elõ a papírral, ollóval, és gyertek barkácsolni!    *****    Tisztítószerek a legjobb áron! Hatékonyság felsõfoka! 333 felmosásra elengedõ általános tisztítószer! Vásároljon még ma!    *****    Hayashibara Megumi és Okui Masami rajongói oldal! Albumok, dalszövegek, és sok más. Folyamatosan frissülõ tartalom.    *****    A legfrissebb hírek a Super Mario világából és a legteljesebb adatbázis a Mario játékokról.Folyamatosan bõvülõ tartalom.    *****    333 Felmosásra elegendõ! Szeretne gazdaságosan felmosni? Szeretne kiváló általános tisztítószert? Kiváló tisztítószerek!    *****    Ha tél, akkor téli sportok! De akár videojáték formájában is játszhatjuk õket. A 1080°Snowboarding egy kiváló példa erre