Kaj sploh je paketno programiranje? Ko še nismo imeli grafičnih operacijskih sistemov, kot so Windows, Mac OS in podobni, se je bolj ali manj vse dogajalo v ukazni vrstici. Prek nje smo vnašali najrazličnejše ukaze, med drugim tudi zaganjali različne programe. Paketno programiranje je nastalo kot orodje, s katerim je bilo mogoče poenostaviti ponavljajoče se postopke. Zadeva je potekala tako, da smo zaporedje ukazov vpisali v besedilno datoteko, to shranili s končnico BAT (krajše za batch), stvar pa zagnali tako, da smo v ukazno vrstico vpisali ime datoteke, v kateri je bil ta skript shranjen. Ker smo ukaze izvedli v paketu (batch) in nam ni bilo treba pisati vsakega posebej, se je temu reklo paketno ali batch programiranje.

Nabor ukazov v paketnem programiranju je bil seveda omejen z naborom ukazov v operacijskem sistemu in je zato bil seveda bolj skromen. Ko so grafični operacijski sistemi prišli tako daleč, da so bile tudi sistemske funkcije dosegljive prek grafičnega vmesnika, se je paketno programiranje umaknilo nekoliko v ozadje. Sčasoma pa se je, predvsem kar zadeva sistemske zadeve, pokazalo, da grafični vmesniki niso vsemogočni in da so nekatere stvari bolj elegantno, predvsem pa preprosto izvedljive s paketnim programiranjem. Zato so pozneje nastala orodja, kot so VBScript, PowerShell in podobna, ki so omogočala precej več kot osnovno paketno programiranje, njihova osnovna filozofija pa je bila dokaj podobna. Omenjeni orodji sta bolj namenjeni vzdrževalcem sistemov, saj ju je treba tudi posebej namestiti, osnovno paketno programiranje pa je dostopno vsem uporabnikom Windowsov, ne glede na različico, ki jo uporabljajo. Sicer gre res za nekaj, kar je »za opicami«, kot bi dejali nekateri, a še vedno omogoča izvedbo nekaterih funkcij, ki jih drugače ne moremo izvesti ali pa je zanje treba namestiti kak poseben program. Pa si oglejmo, kako poteka paketno programiranje in kaj lahko z njim naredite.

ZAČETNI PAKETI

Zapisali smo, da so paketne datoteke navadne besedilne datoteke, v katere zapišemo ustrezne ukaze in vse skupaj shranimo v datoteko s končnico BAT. Za izdelavo paketnih datotek torej ne potrebujemo nobenega dodatnega orodja, saj je dovolj že Beležnica v Windowsih. Datoteke lahko shranimo tudi s končnico CMD, kar je pravzaprav enako kot BAT, le da gre za novejšo različico, ki je 16-bitni sistemi ne poznajo. A ker skoraj zagotovo 16-bitnega sistema ne uporabljate več, je torej vseeno, ali datoteko shranite s končnico BAT ali CMD.

Tak paketni program zaženemo tako, da ga dvokliknemo v Raziskovalcu ali kakšnem drugem programu za delo z datotekami, ali pa znotraj Windowsov njegovo ime vpišemo v ukazno vrstico ali ukazni poziv, kot se tudi imenuje. Do ukazne vrstice pridemo tako, da zaženemo program CMD. V Windowsih XP do njega pridemo tako, da izberemo Start> Zaženi, nato pa v ukazno vrstico vpišemo CMD, v poznejših različicah Windowsov pa CMD vpišemo v vrstico iskanja. Sicer je mogoče programe zagnati iz Start> Zaženi ali iskalne vrstice tudi neposredno, vendar s pomembno razliko: ko se bo program izvedel, se bo okno programa zaprlo (razen če posebej ne ukažemo drugače) in ne bomo videli, ali smo morebiti dobili kakšno sporočilo. Zato je mogoče bolje uporabljati ukazni poziv, seveda odvisno od namembnosti programa. Če nam je na zaslonu izpisan rezultat pomemben, potem vsekakor, če gre za kakšno čiščenje ali kaj podobnega, pa mogoče niti ne.

Preden začnemo samo programiranje, je treba povedati še, kako datoteko tipa BAT ali CMD sploh odpremo za pregled. Če jo dvokliknemo, jo zaženemo, torej ta metoda ne bo delovala. Lahko na primer odpremo Beležnico ali kak podoben program, nato pa v njem prek pogovornega okna za odpiranje datotek poiščemo želeno datoteko in jo odpremo. A to je dokaj neroden postopek. Najlažje je, da datoteko poiščemo v Raziskovalcu, jo kliknemo z desno tipko in izberemo ukaz Urejanje, ki se pokaže v priročnem meniju.

Paketne datoteke najlažje odpremo tako, da jih desno kliknemo in iz priročnega menija izberemo Urejanje.

Tako, zdaj smo opremljeni z osnovnim znanjem in lahko se lotimo programiranja. Paketne datoteke so, kar zadeva strukturo, dokaj preproste. Gre za zaporedje ukazov, ki smo jih poznali v starem DOS-u (in ki so v sistemu dosegljivi še zdaj), vpisani eden za drugim, vsak v svoji vrsti. Če smo v starem DOS-u na primer hoteli prikazati korenski, torej osnovni imenik diska C, smo morali vpisati dva ukaza.

cd c:\
dir /w

Prvi ukaz nas je »prestavil« v osnovni imenik diska C, z drugim pa smo sprožili izpis (dir) vsebine tako, da se je seznam datotek na zaslonu izpisal v več stolpcih (/w). Če zdaj ta ukaza vpišemo v besedilno datoteko, to pa nato shranimo na primer z imenom Korenski.bat, lahko celoten postopek izvedemo tako, da zaženemo datoteko Korenski.bat. To naredimo tako, da v ukaznem pozivu v mapi, kamor smo shranili datoteko, vpišemo njeno ime, s čimer jo zaženemo. Na zaslonu se bo izpisala vsebina osnovnega imenika diska C. Če malo pogledamo to okno ukaznega poziva, vidimo, da so se med zagonom izpisovali tudi ukazi, tako da je vse skupaj popolnoma enako, kot če bi vse skupaj pisali ročno. Če hočemo, da se vsebina imenika izpiše tako, da so datoteke zapisane ena pod drugo, prikažejo pa se tudi podrobnosti, lahko izpustimo stikalo /w, torej se bo ukaz glasil samo dir.

Preprost paketni programček (levo), s katerim bomo izpisali vsebino korenskega imenika diska C. Ko ga zaženemo, se res izpiše njegova vsebina (desno).

No, zdaj pa zadevo malce zapletimo oziroma jo naredimo bolj simpatično. Izpis ukazov (dir, cd …) se imenuje tudi »echo«. Če hočemo, da se ukazi ne izpisujejo, lahko z ukazom 'echo off' izpis preprečimo. Težava je le, da se bo ukaz 'echo off' vseeno videl, saj se paketni ukazi izvajajo drug za drugim in bomo šele s tem ukazom prikazovanje prekinili. No, obstaja pa »trik«, s katerim lahko tudi to preprečimo. To naredimo tako, da pred ukaz 'echo off' postavimo znak '@'. Naš paketni program se bo torej zdaj glasil:

@echo off
cd c:\
dir /w

Da na zaslonu ne bo gneče, ga lahko pred izpisom vsebine tudi počistimo z ukazom 'cls'. Ko se bo izpis končal, je dobro, da se počaka, da uporabnik pritisne kakšno tipko. Če program zaganjamo iz Raziskovalca, se bo namreč okno takoj po izvedbi zaprlo in vsebine ne bomo videli. To je primer, o katerem smo pisali kak odstavek nazaj, kjer smo zapisali, da se bo okno programa zaprlo, razen če ne ukažemo drugače. No, to »drugače« je ukaz 'pause'. Naš program zdaj dobi obliko:

@echo off
cls
cd c:\
dir /w
pause

Da pa bomo vseeno vedeli, kaj program dela, mu dodajmo, tako za šalo, še ukaz, s katerim bo na zaslonu izpisal, da sledi seznam datotek korenskega imenika. Ker smo prej z ukazom '@echo off' preprečili izpisovanje, ga moramo zdaj spet vključiti, da lahko zapišemo, kar bi želeli. To naredimo tako, da spet vpišemo ukaz 'echo'. Ukaz ima načeloma dva argumenta, to sta 'on' in 'off'. Kar koli drugega zapišemo za ukazom, se bo izpisalo na zaslonu. Poleg tega pa naj se doda še prazna vrstica, da bo vse skupaj bolj pregledno. Prazno vrstico vstavimo tako, da za ukaz echo brez presledka vpišemo piko. Naš program bo torej videti tako:

Na desni strani smo zaradi lažjega razumevanja zapisali tudi posledice vsakega ukaza posebej.

Z malo dodatki lahko s paketnim programom dobimo zelo nazorno izpisane podatke.

Seveda pa se v praksi paketnega programiranja ne boste ubadali s trivialnimi zadevami, kot je na primer izpis vsebine neke mape, ampak boste paketno programiranje uporabljali za kaj bolj konkretnega, recimo za varnostno kopiranje datotek. Pri tem boste uporabili ukaze, kot so 'copy' ali 'move', če uporabljate Windowse 7, pa lahko uporabite tudi ukaz 'robocopy'. Če vas zanima, kaj ta dela, v ukazno vrstico vpišite ukaz 'robocopy /?' (brez opuščajev, seveda), in izpisale se vam bodo vse možnosti, ki jih program ponuja.

Zapisal smo, da je izpis vsebine mape nekaj trivialnega. A ni nujno tako. Včasih se na primer zgodi, da bi radi nekam zapisali ali nekomu poslali seznam datotek, ki jih imamo v neki mapi. Kako to narediti? Z orodji znotraj Windowsov, na primer Raziskovalcem ali čim podobnim, to ne gre. Obstajajo sicer programi, ki to znajo narediti, vendar je te treba poiskati in namestiti. Gre na primer precej lažje, če uporabimo ukaz 'dir', s tem da njegov izpis z zaslona preusmerimo v datoteko. To naredimo tako, da za ukaz dodamo znak '> ' in vpišemo ime datoteke, v kateri naj se vsebina zapiše. Če hočemo, da se vsebina imenika vpiše v datoteko Vsebina.txt, se ukaz torej glasi:

dir > Vsebina.txt

Ta ukaz lahko vključimo v naš program, in ko ga zaženemo, se bo namesto izpisa vsebine na zaslonu na disku tvorila datoteka Vsebina.txt, v kateri bo v besedilni obliki to, kar bi se drugače izpisalo na zaslonu. To pa je lahko koristno.

ZDAJ PA ZAPLET

Dokler delamo z datotekami na vnaprej določenih mestih, je paketno programiranje dokaj enostavno, saj je dovolj, če uporabimo nekaj omenjenih preprostih ukazov. Če hočemo naše programe narediti bolj vsestranske, pa se stvari lahko hitro zapletejo. Vzemimo, da bi radi, da naš program Korenski.bat ne prikaže več le vsebine korenskega imenika diska C, ampak vsebino katerega koli imenika. Kako to narediti?
Zadeva je dokaj preprosta, saj moramo namesto ukaza 'cd c:\' uporabiti ukaz 'cd %1'. Ta '%1' je ukaz, ki omogoča, da se namesto tega zapisa vpišejo argumenti, ki jih poda uporabnik. Program se bo glasil:

@echo off
cls
echo Vsebina imenika %1:
echo.
cd %1
dir
pause

Če bomo zdaj program zagnali z ukazom Korenski c:\temp, se bo izpisala vsebina mape temp na disku C. Seveda zdaj mogoče ni več umestno, da se naš program imenuje Korenski, ampak ga lahko preimenujemo v kaj drugega, recimo Vsebina.bat. S tem smo torej naš izhodiščni program naredili bolj uporaben, saj je primeren za izpis vsebine katere koli mape. Če vam po naključju zadeva ne deluje tako, kot bi radi, oziroma se nekatere mape ne izpisujejo, se prijavite v sistem kot skrbnik in stvar bo delovala.

Seveda pa je zadevo mogoče še bolj zaplesti. Kaj pa, če uporabnik ne vpiše nobenega argumenta za ukazom za zagon? Za tak primer bi bilo mogoče dobro, če bi določili neko privzeto mapo, katere vsebina se bo izpisala. Za kaj takšnega pa moramo poseči po malce bolj naprednih zadevah - spremenljivkah, s katerimi bomo nadzirali dogajanje. Naš program bomo spremenili, da se bo glasil takole:

V programčku zdaj vidimo nekaj novosti. Prav je ta, da smo dodali ukaz 'setlocal' in ga zaključili z 'endlocal'. Ukaza načeloma nista nujno potrebna, sta pa koristna. Določata namreč, da bodo vse spremenljivke, ki jih vpisujemo v program oziroma skript, lastne le temu programu in ne celotnemu sistemu. Sicer se sodobni sistemi ne bodo sesuli, če bodo morali shraniti nekaj dodatnih bajtov, a gre za načelo, kjer je dobro to, kar je lokalno, tudi obdržati lokalno. Bolj pomembna je četrta vrstica. Z ukazom v njej preverjamo, ali je uporabnik vpisal argument oziroma ali je program zdaj, ko smo ga iz Korenski.bat preimenovali v Vsebina.bat, zagnal z ukazom na primer Vsebina c:\temp ali le z Vsebina. Če argumenta ni, torej je %1 prazno (oglati oklepaj in zaklepaj), potem v naslednji vrstici določimo, naj spremenljivka 'mapa', ki smo jo uvedli, dobi vrednost c:\. Če pa argument je, potem naj se ta priredi spremenljivki 'mapa'. Nadaljevanje programa je enako kot prej, le ukaz 'cd' se spremeni tako, da je za njim namesto %1 vpisana spremenljivka 'mapa'.

Gre pa tudi drugače:

Vidimo, da smo zadevo rešili nekoliko drugače, in to tako, da smo rekli, naj bo argument pri vpisu ukaza spremenljivka z imenom 'mapa'. Nato smo rekli, da če spremenljivka je oziroma če njeno mesto ni prazno ([]), naj se izvajanje programa nadaljuje z vrstico 'ni_prazno', če pa je pogoj izpolnjen, torej je spremenljivka prazna oziroma uporabnik za imenom programa ni vpisal mape, katere vsebino bi rad videl, naj se spremenljivka postavi na c:\. Nadaljevanje je enako kot prej.

Gremo naprej z našimi izboljšavami. Naš program zdaj deluje tako, da ga zaženemo na način, da vpišemo njegovo ime, nato pa kot argument vpišemo mapo, katere vsebino bi radi prikazali na zaslonu. Če argumenta ni, se bo izpisala vnaprej določena mapa, v našem primeru c:\. To je sicer bolje kot začetni program, vendar še daleč od nečesa res uporabnega. Zadeva bo res uporabna takrat, ko bo uporabnik moral vpisati mapo in tako programu povedati, kaj naj izpiše. Modifikacija je minimalna, saj se bo nov program glasil:

Kaj smo naredili? Vse je ostalo enako kot prej, le namesto da bi neposredno »vprogramirali« mapo C:\, uporabnika vprašamo za želeno mapo. Če je ne vpiše, se vprašanje ponovi. To pomeni, da lahko zdaj program zaženemo brez argumenta, samo z imenom, in nas bo vprašal, katero mapo želimo. Ko jo vpišemo, izpiše njeno vsebino, če je ne, vprašanje ponovi.

Zdaj je program že bolj prijazen. Vpraša nas, vsebino katere mape bi želeli izpisati. Če jo vpišemo, sledi izpis, če ne, se vprašanje ponovi. Desno na vrhu vidimo, da se je vprašanje ponovilo, saj nismo vpisali ničesar, ko pa smo vpisali mapo c: emp, se je izpisala njena vsebina.

Tako, izdelali smo dokaj prijazen paketni programček, ki nam izpisuje vsebino katere koli mape. Sicer z njim nismo izvedli programerske revolucije, smo vam pa prikazali, kaj vse je mogoče narediti kar znotraj sistema brez dodatnih programov in orodij. Dovolj je Beležnica in nekaj znanja. Seveda pa to še zdaleč ni vse, kar je mogoče narediti s paketnim programiranjem. Zadeve so lahko še bolj kompleksne in z njimi je mogoče narediti tudi kaj bistveno bolj zapletenega. A za začetek naj bo dovolj. Če vas tematika res zanima, nam pišite, pa bomo v kakšni od naslednjih številk Mojega mikra prikazali še kakšno bolj napredno metodo. A za tokrat naj bo dovolj.

Moj mikro, Februar 2012 | Zoran Banovič |