/motto<"Small is beautiful.">
 
/chapter</ii<Komentotiedosto>t>
 
Yksinkertaisimmassa muodossaan komentotiedosto (/ii<script> file)
on vain joukko tiedostoon kirjoitettuja </sc unix>in komentoja.

Komentotiedostoille voidaan my|s v{litt{{ argumentteja,
ja niiss{ voidaan k{ytt{{ useimpia ohjelmointikieliss{
esiintyvi{ kontrollirakenteita, joten varsin
monimutkaisiakin asioita voidaan tehd{ komentotiedostojen
avulla tarvitsematta kirjoittaa varsinaisia ohjelmia.
Kysymyksess{ on kuitenkin tulkittava kieli, joten
v{h{nkin raskaampaa laskentaa ja monta kertaa toistettavia 
silmukoita edellytt{v{t teht{v{t tulee aina kirjoittaa
jollakin ohjelmointikielell{.
 
Tarkastelemme seuraavassa vain /ii<Bourne-shell>in
ymm{rt{mi{ komentotiedostoja.
 
/section<Komentotiedoston suorittaminen>
 
Oletetaan, ett{ olemme tallettaneet tiedostoon </tt dec>
(mik{ tietenkin tulee sanoista ''directory entry count'',
kuten kaikki </sc unix>in harrastajat heti arvaavat)
tekstin
 
</copymode
      ls /char'174 wc -l
>
 
Voimme tehd{ tiedostosta </tt dec> suorituskelpoisen
tiedoston ja suorittaa sen komennoilla
 
</copymode
      chmod u+x dec
      dec
>
 
(Olettaen, ett{ nykyhakemisto sis{ltyy hakupolkuun.)
Toinen tapa on sy|tt{{ tiedosto komentotulkille
sanomalla
 
</copymode
      sh dec
>
 
T{ll{ tavoin voidaan k{ytt{{ Bourne-shelli{ tulkitsemaan
komentotiedostoamme, vaikka oletustulkkina olisikin C-shell.
 
Normaalisti komentotiedoston suoritus k{ynnist{{
uuden kopion komentotulkista.
T{m{ voidaan est{{ k{ytt{m{ll{ komentoa, jota merkit{{n
ytimekk{{sti pisteell{:
/iii<.>
 
</copymode
      . dec
      . .//dec
>
 
T{ll|in nykyinen komentotulkki lukee seuraavat
komentonsa tiedostosta </tt dec>.
 
Huomaa, ett{ pistett{ seuraa v{lily|nti;
muuten se tulkittaisiin osaksi tiedoston nime{.
T{ll{ tavoin suoritettava komentotiedosto poikkeaa
toisessakin suhteessa tavallisista komentotiedostoista:
sille ei voi v{litt{{ argumentteja.
 
 
/section</ii<Komentotiedoston argumentit>>

Tehd{{n kokeeksi tiedosto </tt x>, joka sis{lt{{
seuraavan rivin:

</copymode
      chmod +x /$1
>

Jos nyt sanomme 

</copymode
      x ohjelma
>

t{m{ toimii ik{{nkuin olisimme antaneet komennon

</copymode
      chmod +x ohjelma
>

ja muuttaa siis tiedoston </tt ohjelma> suojauksia niin,
ett{ se voidaan suorittaa.

Merkkijono </tt/$1> viittaa komentotiedoston ensimm{iseen
argumenttiin.  Seuraaviin argumenttehin viitataan
vastaavasti muuttujilla </tt/ii</$1>>, </tt/$2> jne. 
Muita hy|dyllisi{ muuttujia ovat mm.  </tt/ii</$/#>>, joka
kertoo argumenttien m{{r{n (desimaalilukuna, uskomatonta!)
ja </tt/ii</$0>>, joka ilmoittaa nimen, jolla
komentotiedosto on k{ynnistetty.  </sc Unix>issa on n{et
mahdollista, ett{ komennon nimi on vain /ii<linkki>
tiedostoon, ja useampi komento voi itse asiassa k{ynnist{{
saman tiedoston.  T{ll|in komentokielinen ohjelma katsoo,
mill{ nimell{ se on k{ynnistetty ja valitsee sen mukaan
toimintatapansa. 
 
Yritet{{n nyt muuttaa edellist{ komentoamme </tt dec> siten,
ett{ laskettavien tiedostojen joukkoa voitaisiin rajoittaa.
Kirjoitetaan tiedosto muotoon
 
</copymode
      ls /$1 /char'174 wc -l
>

Oletetaan, ett{ hakemistossamme on tiedostot
</tt roska.c> ja </tt rotta.c>. Sanomme kokeeksi
 
</copymode
      sh dec *.c
>

Ihmeeksemme t{m{ kirjoittaa p{{tteelle ykk|sen.
Syyn{ on se, ett{ /ii<jokerimerkin> k{sitteleekin jo
komentotulkki, joten komentomme vastaa k{sky{
 
</copymode
      ls roska.c /char'174 wc -l
>

Ongelman voimme kiert{{ usealla tavalla. Er{s mahdollisuus
on lainata tiedostoluettelo:

</copymode
      sh dec '*.c'
>

jolloin komentotulkki ei p{{se evaluoimaan </tt *.c>:t{.
Toinen, siistimpi tapa on kirjoittaa komentotiedosto
esimerkiksi muotoon

</copymode
      ls /$@ /char'174 wc -l      
>

Merkint{ </tt/ii</$@>> tarkoittaa komentotiedoston
argumenttilistaa sellaisenaan.
 
Esimerkiksi silmukat olisi usein helpointa kirjoittaa siten,
ett{ sama muuttuja viittaa aina seuraavana k{sittelyvuorossa
olevaan argumenttiin.  T{m{ saadaan aikaan komennolla
 
</copymode
      shift
>
 
/iii<shift>
jonka vaikutuksesta ensimm{isen argumentin arvo
katoaa tyystin, </tt/$1> rupeaa osoittamaan
toiseen argumenttiin. </tt/$2> kolmanteen jne.
 
 
 
/section</ii<Ymp{rist|muuttujat>>
 
Edell{ esiintyneet </tt/$>-alkuiset symbolit
ovat itse asiassa shellin paikallisia muuttujia,
joille annetaan arvot shelli{ k{ynnistett{ess{.

T{ss{ muuttujilla tarkoitetaan ns.  </sl ymp{rist|muuttujia>
(/ii<environmental variables>), jotka ovat
</sc unix>-k{ytt|j{rjestelm{n (ja Bourne shellin) paikallisia
muuttujia.  /ii<C-shell>ill{ on viel{ erilliset ikiomat
/ii<shell-muuttuja>t, joita /ii<Bourne shell> ei tunne.  C-shelliss{
ymp{rist|muuttujia asetetaan komennolla </tt/ii<setenv>>, ja
shell-muuttujia komennolla </tt/ii<set>>. 

Muitakin ymp{rist|muuttujia voidaan luoda mielin m{{rin.
Sanomalla
 
</copymode
      var=value
>
 
m{{rittelemme muuttujan </tt var>, jonka arvoksi 
tulee merkkijono </tt value>. Huomaa, ett{ </tt =>-merkin
kummallakaan puolella ei saa olla v{lily|ntej{.
 
Voimme katsoa, mik{ muuttujamme arvo mahtaa olla
sanomalla
 
</copymode
      echo /$var
>
 
/iii<echo>
Komentotulkki vastaa t{h{n iloisesti, ett{
 
</copymode
      value
>
 
</tt/$>-merkki muuttujan nimen edess{ on 
operaattori, joka kertoo, ett{ seuraava merkkijono
on muuttujan nimi ja t{m{n muuttujan arvo on
evaluoitava. Jos kirjoitamme muuttujan nimen
ilman dollarin merkki{
 
</copymode
      echo var
>
 
ei tulkki suostu evaluoimaan muuttujaa
(rahaahan se </sc unix>kin kaipaa), vaan
palauttaa vain merkkijonon sellaisenaan:
 
</copymode
      var
>
 
Jos muuttujan arvoa seuraa v{litt|m{sti kirjain
tai numero, muuttujan nimi on kirjoitettava
aaltosulkuihin. Esimerkiksi
 
</copymode
      t=//tmp//tation//
      prog /gt /$/lbc<t>/rbc<s>
>
 
ohjaa ohjelman </tt prog> tulostuksen tiedostoon
</tt //tmp//tation//s>.
 
Muuttujien evaluointia voi s{{nn|stell{
heittomerkeill{. Heittomerkkeihin
suljettu merkkijono edustaa aina vain itse{{n; 
mit{{n sen sis{ll{ olevia olioita ei evaluoida.
Lainausmerkkien sis{ss{ olevat
muuttujat sensijaan korvataan arvoillaan
(/ii<parameter substitution>).
Seuraavat komennot 
/iii<merkkijonon lainaaminen>
/iii<'...'>
/iii<"...">
 
</copymode
      var=value
      echo 'var=/$var'
      echo "var=/$var"
>
 
tulostavat siten
 
</copymode
      var=/$var
      var=value
>
 
Kolmas tapa on sulkea merkkijonona nurinp{isten heittomerkkien
v{liin (</tt/ii<` ... `>>). T{ll|in merkkijono on jokin
komento, joka suoritetaan, mahdolliset muuttujat evaluoidaan
ja merkkijonon arvona palautetaan komennon normaalisti
tiedostoon </tt stdout> tuottama tulostus (/ii<command substitution>). 
Esimerkiksi komento
 
</copymode
      dir=`pwd`
>
 
asettaa muuttujan </tt dir> arvoksi </tt pwd>:n tulostuksen
eli nykyhakemiston nimen.
 
 
M{{ritellyt ymp{rist|muuttujat ja niiden arvot saa
selville sanomalla /iii<set>
 
</copymode
      set
>
 
/iii<muuttujien periytyminen>
Muuttujat ovat shellin paikallisia olioita.
Suoritettaessa jotakin ohjelmaa tai komentotiedostoa
luodaan uusi /ii<aliprosessi>, joka ei en{{ tunne n{it{
muuttujia. Mik{li muuttujien halutaan
periytyv{n my|s aliprosesseille, ne on m{{ritelt{v{
periytyviksi komennolla </tt/ii<export>>. Esimerkiksi
komentojen
 
</copymode
      mita=juokse
      minne=suolle
      export mita minne
>
 
j{lkeen suoritettavat komennot havaitsevat, ett{
muuttujilla </tt mita> ja </tt minne> on arvot
</tt juokse suolle>.
 
Voisimme kirjoittaa edellisen esimerkin rivit
komentotiedostoon </tt huihai> ja suorittaa sen
sanomalla </tt .//huihai>. Jos sen j{lkeen katsomme
komennolla </tt set>, mit{ muuttujia meill{ oikein on,
huomaamme, etteiv{t </tt mita> ja </tt minne> olekaan
m{{riteltyj{. 
Syy t{h{n on se, ett{ komentotiedoston suoritusta varten
k{ynnistyy aliprosessina uusi komentotulkki,
ja muuttujat periytyv{t vain kyseisen
komentotiedoston synnytt{mille j{lkel{isille, mutta
eiv{t sen k{ynnist{neelle prosessille (t{ss{ suhteessa
k{ytetty biologinen terminologia on siis ihan korrektia).
Jos haluamme saada komentotiedoston asettamat muuttujat
yleisemp{{nkin tietoisuuteen, on nykyisen shellin
tulkittava komentotiedoston komennot. Ja t{m{h{n k{y sanomalla
/iii<.> 

</copymode
      . .//huihai
>
 
 
Valmiiksi m{{riteltyj{ muuttujia ovat mm. seuraavat:
 
</tt/ii</$TERM>>
 
P{{tetyyppi. Jos p{{tteesi k{ytt{ytyy kummallisesti, 
tarkista ensin, onko muuttujan </tt /$TERM> arvo oikein
ja tarpeen mukaan aseta se esimerkiksi seuraavasti
 
</copymode
      TERM=vt100
      export TERM
>
 
Voit tietenkin sijoittaa n{m{ komennot my|s tiedostoon
</tt/ii<.profile>>, jolloin ne suoritetaan automaattisesti
ottaessasi yhteyden koneeseen.
 
</tt/ii</$HOME>>
 
Kotihakemiston nimi.
 
</tt/ii</$PATH>>
 
/ii<Hakupolku>. Kun k{ytt|j{rjestelm{{ pyydet{{n suorittamaan
jokin tiedosto, haetaan tiedostoa hakupolussa m{{ritellyist{
hakemistoista, kunnes sopivan niminen tiedosto (ohjelma tai
komentotiedosto) l|ytyy. Hakupolun saa selville antamalla
komennon
 
</copymode
      echo </$>PATH
>
 
Tuloksena voi olla esimerkiksi
 
</copymode
      //bin://usr//bin://usr//ucb://usr//lbin://csc//appl//setup
>
 
T{m{ tarkoittaa, ett{ komentoa etsit{{n ensin hakemistosta
</tt //bin>, sitten hakemistosta </tt //usr//bin> jne.
Jos hakupolussa on piste, haetaan komentoa my|s
nykyhakemistosta. Turvallisuussyist{ Crayll{ on
oletusarvona, ett{ /ii<nykyhakemisto> ei sis{lly hakupolkuun.
Halutessasi voit kyll{ lis{t{ sen sanomalla
 
</copymode
      PATH=</$>PATH:.
      export PATH
>
 
Lis{{ piste aina hakupolun loppuun, {l{ koskaan sen alkuun!
Ellei nykyhakemisto ole hakupolun varrella, voit suorittaa
siell{ olevan ohjelman ilmoittamalla hakemiston nimen:
 
</copymode
      .//ohjelma
>
 
Jos nykyhakemisto on hakupolussa, riitt{{ pelkk{
 
</copymode
      ohjelma
>
 
 
 
/section</ii<Test>-komento>
 
Komennolla </tt test> voidaan testata useita erilaisia
asioita.  Komento on hy|dyllinen seuraavassa esitelt{vien
ehdollisten rakenteiden ja silmukoiden yhteydess{.  Muutamia
tavallisia komennon k{ytt|tapoja ovat seuraavat:
 
</copymode
      test -f </sl file>
>
 
Palauttaa /ii<paluukoodi>na nollan, jos tiedosto
</sl file> on olemassa eik{ ole hakemisto, ja
nollasta poikkeavan arvon muuten.
 
</copymode
      test -d </sl file>
>

Testaa, onko tiedosto </sl file> hakemisto.
 
</copymode
      test -r </sl file>
> 
Testaa, onko tiedosto </sl file> luettavissa.
 
</copymode
      test -w </sl file>
>

Testaa, voiko tiedostoon </sl file> kirjoittaa.
 

/section</ii<Kontrollirakenteet>>

/iii<toistorakenne>  /iii<for>
Usein halutaan toistaa sama operaatio kaikille
komentorivill{ annetuille argumenteille.
T{m{ voidaan tehd{ sanomalla
 
</copymode
      for i 
      do
          dosomething /$i
      done
>
 
Toistorakenteen yleinen muoto on
 
</copymode
      for </sl variable> in </sl values>
      do </sl commands>
      done
>
 
Jos </tt in ...> -osa puuttuu, oletetaan, ett{
k{yd{{n l{pi kaikki komentotiedostolle
v{litetyt argumentit.
 
Toistorakenteen muita mahdollisia muotoja ovat
/iii<while> /iii<until> 

</copymode
      while </sl commands1>
      do </sl commands2>
      done
>
 
</copymode
      until </sl commands1>
      do </sl commands2>
      done
>
 
N{iss{ suoritetaan joukko komentoja, </sl commands1>, ja
viimeisen /ii<paluukoodi> m{{r{{ </tt while>- tai </tt
until>-testin totuusarvon.  Nolla tarkoittaa komennon
onnistumista ja vastaa siis totuusarvoa tosi.  Jos
paluukoodi on jotain muuta, meni jokin asia pieleen. 
Nollasta poikkeava arvo vastaa totuusarvoa ep{tosi.  Huomaa,
ett{ t{m{ on johdonmukaisesti t{sm{lleen p{invastoin kuin
C-kieless{!
 
Esimerkiksi seuraava silmukka odottelee, kunnes
joku {ly{{ tehd{ sit{ miellytt{v{n tiedoston:
 
</copymode
      until test -f nightmare
      do 
         sleep 600
      done
>
 
T{m{ k{y katsomassa, olisiko olemassa tiedostoa
</tt nightmare>; ellei, uinahdetaan kymmeneksi
minuutiksi ja katsotaan sitten taas uudestaan.
 
Komentojen ehdollista suoritusta varten on 
olemassa rakenteet /iii<if> /iii<ehdollinen rakenne>
 
</copymode
      if </sl commands1>
      then </sl commands2>
      fi
 
      if </sl commands1>
      then </sl commands2>
      else </sl commands3>
      fi
>
 
Sis{kk{iset ehdolliset rakenteet
 
</copymode
      if ...
      then ...
      else if ...
           ...
           fi
      fi
>
 
voidaan kirjoittaa my|s lyhyemmin:
 
</copymode
      if ...
      then ...
      elif ...
      ...
      fi
>
 
Valinta useammasta vaihtoehdosta voidaan tehd{ my|s
</tt/ii<case>>-rakenteella: /iii<valintarakenne>
 
</copymode
      case </sl word> in
      </sl pattern1>) </sl commands1> ;;
      </sl pattern2>) </sl commands2> ;;
      ...
      </sl patternn>) </sl commandsn> ;;
      esac
>
 
T{ss{ kukin </sl pattern> on merkkijono, joka voi
sis{lt{{ mm. jokereita </tt ?> ja </tt *>. 
Muuttujan </sl word> arvoa verrataan j{rjestyksess{
n{ihin merkkijonoihin, kunnes l|ytyy
ensimm{inen, johon se t{sm{{.
 
Esimerkin vuoksi teemme scriptin </tt compile>, joka k{{nt{{
(ja linkitt{{) argumenttina annetun tiedoston eri k{{nt{jill{
riippuen annetusta optiosta.

</copymode
      case /$1 in
      -c)  cc /$2.c ;;
      -f)  cft77 /$2.f
           segldr /$2.o ;;
      -p)  pascal -i /$2.p 
           segldr a.o ;;
       *)  echo illegal option /$1 ;;
      esac
>
 
Nyt voisimme sitten k{{nt{{ C-ohjelman </tt burp.c>
sanomalla </tt compile -c burp>.

Komentoja voidaan ryhmitell{ kahdella eri tavalla
/iii<komentojen ryhmittely> /iii</lbc ... /rbc> /iii<( ... )>
 
</copymode
      /lbc</sl command> ; </sl command> ; ... /rbc
      (</sl command> ; </sl command> ; ... )     
>
 
Edellinen suorittaa komennot per{kk{in
tavanomaiseen tapaan, mutta j{lkimm{inen
k{ynnist{{ lis{ksi niiden suoritusta varten
uuden shellin, joten esimerkiksi komento
 
</copymode
      (cd //tmp ; rm *)
>
 
k{y tuhoamassa kaikki tiedostot hakemistosta </tt//tmp>,
mutta </tt cd>:n vaikutus j{{ vain uuden shellin
tietoon, joten nykyhakemisto ei komentojen suorituksen
j{lkeen ole muuttunut.
 

/section</ii<Alustustiedostot>>
 
Ottaessasi yhteyden tietokoneeseen suoritetaan aina sek{
j{rjestelm{n ett{ k{ytt{j{n oma komentotiedosto, jotka mm. 
alustavat erilaisia muuttujia.  K{ytt{j{n alustustiedostot
ovat kotihakemistossa ja niiden nimet alkavat pisteell{,
jolloin ne eiv{t n{y tavallisessa tiedostoluettelossa. 
 
/ii<Bourne-shell>i{ k{ytett{ess{ k{ytt{j{n alustustiedosto on
</tt/ii<.profile>>. /ii<C-shell>iss{ puolestaan suoritetaan tiedostot
</tt/ii<.cshrc>> ja </tt/ii<.login>>.
My|s k{ynnistett{ess{ uusi kopio C-shellist{ suoritetaan
</tt .cshrc> aina uudestaan.

Seuraavassa on esimerkki Crayn </tt .profile> -tiedostosta, jolla saadaan
interaktiivisessa k{yt|ss{ k{ytt||n C-shell:

</copymode
/catcode`/[=12
/catcode`/]=12
      if [ "/$ENVIRONMENT" != "BATCH" ]
      then
      echo " "
      echo " terminal type ? (vt100)"
      echo " "
      read type
      if test "/$type" = ""
      then
         TERM=vt100;export TERM
      else
         TERM=/$type;export TERM
      fi
      exec //bin//csh
      fi
>

T{ss{ tarkistetaan ensin onko ty| interaktiivinen vai er{ty|.
Jos kyseess{ on er{ty|, ei tehd{ muuta. Jos kyseess{ on interaktiivinen
istunto, kysyt{{n p{{tetyyppi{. Jos k{ytt{j{ vastaa kysymykseen 

</copymode
      terminal type ?
>

pelk{ll{ /boxed<Enter>:in painalluksella, tulee p{{tetyypiksi
</tt vt100>. T{m{n j{lkeen interaktiivisessa istunnossa k{ynnistyy
C-shell, joka on itseasiassa </tt //bin//csh> -niminen ohjelma. 
Shellin k{ynnistys tehd{{n t{ss{ komennolla </tt/ii<exec>>,
jolloin ei luoda uutta prosessia, vaan k{ynniss{ oleva
prosessi (vanha komentotulkki) korvataan toisella ohjelmalla
(uudella komentotulkilla).

K{ynnistyess{{n C-shell suorittaa (vain) </tt .cshrc> -tiedoston. Seuraavassa
on esimerkki t{st{:

</copymode
      set prompt = 'cray/% '
      set history = 30
      alias h 'history'
      alias ll 'ls -la'
>

Aloitettaessa uusi shell on hyv{ muuttaa my|s /ii<kehote>tta (promptia).
T{ss{ esimerkiss{ se muutetaan </tt cray/%>:ksi. Kehotteeseen liitet{{n
</tt/%> -merkki, jotta tiedet{{n, ett{ k{yt|ss{ on nyt C-shell.

C-shelliss{ on mahdollisuus ker{t{ vanhoja komentoja talteen, jonka
j{lkeen niihin voi viitata vastaavalla numerolla. Komento
</tt set history = n> m{{rittelee kuinka monta komentoa talletetaan.
Komennolla </tt/ii<history>> voi listata kaikki suoritetut komennot.
Liitteess{ 5 on kohdassa </tt History Mechanism> kuvattu, miten
komentoja voi suorittaa uudelleen.

/iii<komentojen synonyymit>
Toinen interaktiivista ty|t{ helpottava piirre C-shelliss{
on </tt/ii<alias>> - komento.  Sill{ voi tehd{ komennoille
synonyymej{.  Usein k{ytetyille, pitkille komennoille voi
tehd{ n{in lyhyit{ vastineita. 

