Kirjoittaja: Metabolix (05.12.2009)
Bourne shell (sh) on vuonna 1977 julkaistu Unix-käyttöjärjestelmän komentotulkki. GNU/Linux-jakelut, BSD-järjestelmät ja Mac OS X sisältävät yleensä jonkin sh:n kaltaisen komentotulkin. Yleisimpiä vaihtoehtoja ovat bash, ash ja dash, jotka ovat syntyneet vapaan lähdekoodin hankkeiden yhteydessä.
Moni tyytyy vain käynnistämään komentotulkista ("komentoriviltä", "terminaalista" tai "konsolista") muita ohjelmia, mutta todellisuudessa jo komentotulkki itsessään pystyy vaikka mihin: se tukee tekstimuuttujia, taulukoita, ehtolauseita, silmukoita ja funktioita. Näillä voikin jo tehdä monenlaista, ja kun komentotulkista voi vielä ajaa muita ohjelmia, yhteen skriptiin voi koota hyvinkin mutkikkaita toimintoja.
Pelkkiä komentotulkin sisäisiä ominaisuuksia käyttämällä ei saa paljonkaan käytännöllistä aikaan, vaan todelliset toiminnot ovat usein muissa ohjelmissa. Tyypillisiä esimerkkejä ovat suuren kuvajoukon pienentäminen: komentotulkilla voidaan käydä kaikki hakemiston tiedostot läpi, mutta kunkin kuvan pienentämiseen tarvitaan erillinen ohjelma, jolle ilmoitetaan kuvatiedosto ja kuvan haluttu koko.
Tekstiä tulostetaan komennolla echo
:
echo "Montako yötä jouluun on?"
Alkuperäinen Bourne shell ei tukenut laskemista, mutta mm. Bash käyttää tähän syntaksia $((lauseke))
. Ehtojen tarkistaminen tehdään komennolla test, joka voi olla ulkoinen ohjelma tai komentotulkin komento.
#!/bin/sh # Alustetaan alkuarvot A=0 B=1 # Silmukka: Kun B on alle 100. while test $B -lt 100 ; do # Tulostetaan luvut. echo $A echo $B # Lasketaan kaksi seuraavaa lukua. A=$(($A + $B)) B=$(($B + $A)) done
Tämä koodi tulostaa rekursiivisella funktiolla hakemistopuun.
#!/bin/sh # Funktio hakemistopuun listaukseen. listaa() { # Funktion parametrit: ensimmäisenä polku, toisena sisennys. # Lisätään sisennykseen jo tässä vaiheessa merkit " | ". local polku="$1" local sisennys="$2 | " # For-silmukka käy läpi kaikki tiedostot ja hakemistot, joiden alussa # on annettu polku; *-merkki hyväksyy kaikki polun loppuosat. Polun # alun on oletava lainausmerkeissä, jotta välilyönnit toimisivat oikein. for nimi in "${polku}"* ; do # Case-rakenteella tunnistetaan erilaiset nimet. case "${nimi}" in # Jos ei löydy yhtään tiedostoa, termiksi jää # sama "${polku}*", jolla tiedostoja haettiin. # Merkintä ;; lopettaa tapauksen käsittelyn. "${polku}*") ;; # Samaan ja ylähakemistoon viittaavat nimet # ohitetaan, jottei tule ikuista silmukkaa. ".") ;; "..") ;; "*/.") ;; "*/..") ;; # Pelkkä *-merkki hyväksyy mitä vain. # Tässä siis käsitellään hakemistosta löytyneet nimet. *) # Uuden hakemiston kohdalla jatketaan listausta # rekursiivisesti. Tiedostonimet tulostetaan. if test -d "${nimi}" ; then echo "${sisennys}${nimi}/" listaa "${nimi}/" "${sisennys}" else echo "${sisennys}${nimi}" fi ;; esac done } echo "Hakemistopuu:" listaa
Skriptin tuloste voisi olla tällainen:
Hakemistopuu: | kokeilut/ | | listaa.sh | | osoittimet.pas | musiikki/ | | musiikki/putkaorkesteri/ | | | musiikki/putkaorkesteri/intermezzo.mid | | | musiikki/putkaorkesteri/unihiekkaa.mid | | musiikki/sibelius/ | | | musiikki/sibelius/finlandia.mp3 | | | musiikki/sibelius/karelia/ | | | | musiikki/sibelius/karelia/alla_marcia.mp3 | | | | musiikki/sibelius/karelia/intermezzo.mp3
Ohjelmalla basename voisi vielä erottaa tiedostonimistä näytettäväksi vain loppuosan ilman edeltäviä hakemistoja, esimerkiksi "finlandia.mp3".
Eri komentotulkkien syntakseissa ja ominaisuuksissa on eroja, joista on joskus vaikea saada selkoa, koska niitä ei ole aina edes kirjattu muistiin. Ohjelmoija Tom Duff valitteli asiasta jo alkuperäisen sh:n aikaan: "Nobody really knows what the Bourne shell's grammar is. Even examination of the source code is little help." (Vapaa käännös: "Kukaan ei todella tunne Bourne shellin kielioppia. Edes lähdekoodin tutkiminen ei juuri auta.")