Ero sivun ”Bash-skriptaus” versioiden välillä

Siirry navigaatioon Siirry hakuun
4 593 merkkiä lisätty ,  13. syyskuuta 2021
p
ei muokkausyhteenvetoa
(→‎Joukot: Lisätty huomio siitä, mitä bash tulkitsee ja mikä jää suoritettavalla ohjelmalle)
pEi muokkausyhteenvetoa
(43 välissä olevaa versiota 19 käyttäjän tekeminä ei näytetä)
Rivi 3: Rivi 3:
== Alkuun ==
== Alkuun ==
Skripti aloitetaan rivillä
Skripti aloitetaan rivillä
#!/bin/bash
<syntaxhighlight lang="bash">
#!/bin/bash
</syntaxhighlight>
Joka kertoo, että skripti suoritetaan käyttäen bashia riippumatta siitä, mitä komentotulkkia käyttäjä käyttää ajaessaan skriptin. Huomaa, että vaikka rivi alkaa #-merkillä, se ei ole kommentti. Muualla skriptissä #:llä alkavat rivit ovat kommentteja, eikä niitä huomioida.
Joka kertoo, että skripti suoritetaan käyttäen bashia riippumatta siitä, mitä komentotulkkia käyttäjä käyttää ajaessaan skriptin. Huomaa, että vaikka rivi alkaa #-merkillä, se ei ole kommentti. Muualla skriptissä #:llä alkavat rivit ovat kommentteja, eikä niitä huomioida.


Rivi 10: Rivi 12:
=== Ensimmäinen skripti ===
=== Ensimmäinen skripti ===
Tehdään aluksi yksinkertainen skripti, joka esittelee muutamia perustoimintoja:
Tehdään aluksi yksinkertainen skripti, joka esittelee muutamia perustoimintoja:
#!/bin/bash
<syntaxhighlight lang="bash">
echo "Hei, `whoami`, mitä kuuluu"
#!/bin/bash
echo "Olet hakemistossa $PWD, tiedostolistaus:"
echo "Hei, $(whoami), mitä kuuluu"
ls
echo "Olet hakemistossa $(pwd), tiedostolistaus:"
ls
</syntaxhighlight>
Kuten huomaat, skripteissä käytetään tavallisia komentorivikomentoja, jotka sitten suoritetaan järjestyksessä. Toisaalta kuten myöhemmin huomaamme, skriptit tarjoavat paljon enemmän mahdollisuuksia kuin pelkkä komentojen näpyttely konsoliin.
Kuten huomaat, skripteissä käytetään tavallisia komentorivikomentoja, jotka sitten suoritetaan järjestyksessä. Toisaalta kuten myöhemmin huomaamme, skriptit tarjoavat paljon enemmän mahdollisuuksia kuin pelkkä komentojen näpyttely konsoliin.


Rivi 20: Rivi 24:
  Olet hakemistossa /home/kayttaja/ohjelmointi/skriptit, tiedostolistaus:
  Olet hakemistossa /home/kayttaja/ohjelmointi/skriptit, tiedostolistaus:
  eka.sh
  eka.sh
Esimerkistä nähdään heti muutama perusasia. Ensinnäkin toisella rivillä käytetään ohjelmaa [[whoami]], joka tulostaa käyttäjänimen. Kun ohjelma on `-merkkein välissä, kyseiseen kohtaan "kopioidaan" ajetun ohjelman tuloste.
Esimerkistä nähdään heti muutama perusasia. Ensinnäkin toisella rivillä käytetään ohjelmaa [[whoami]], joka tulostaa käyttäjänimen. Kun ohjelma on $()-merkinnän sisällä, kyseiseen kohtaan "kopioidaan" ajetun ohjelman tuloste.


Toisella rivillä käytetään muuttujaa. Muuttujien edessä on dollarimerkki ($), ja niitä voidaan tunkea vaikka merkkijonojen (jotka erotetaan lainausmerkillä) sisälle. Muuttujia käsitellään tarkemmin myöhemmin. Esimerkissä käyttämämme muuttuja <tt>$PWD</tt> on [[ympäristömuuttuja]], jonka arvona on aina se hakemisto, jossa käyttäjä on. Voit kokeilla tätä esimerkiksi kirjoittamalla komentoriville komennon <tt>echo $PWD</tt>.
Toisella rivillä käytetään muuttujaa. Muuttujien edessä on dollarimerkki ($), ja niitä voidaan tunkea vaikka merkkijonojen (jotka erotetaan lainausmerkillä) sisälle. Muuttujia käsitellään tarkemmin myöhemmin. Esimerkissä käyttämämme muuttuja <tt>$PWD</tt> on [[ympäristömuuttuja]], jonka arvona on aina se hakemisto, jossa käyttäjä on. Voit kokeilla tätä esimerkiksi kirjoittamalla komentoriville komennon <tt>echo $PWD</tt>.


Viimeisellä rivillä ajetaan normaalisti komentoriviohjelma [[ls]]. Voit myös kokeilla korvata tämän rivin rivillä
Viimeisellä rivillä ajetaan normaalisti komentoriviohjelma [[ls]]. Voit myös kokeilla korvata tämän rivin rivillä
echo "`ls`"
<syntaxhighlight lang="bash">
echo "`ls`"
</syntaxhighlight>


Skrpti voitaisiin myös kirjoittaa suoraan komentoriville muodossa
Merkintä $() voidaan kirjoittaa myös ``, kuten alla esimerkissä. Tällöin kuitenkaan ei voi käyttää sisäkkäisiä komentoja.
echo "Hei, `whoami`, mitä kuuluu"; echo "Olet hakemistossa $PWD, tiedostolistaus:"; ls;
 
Skripti voitaisiin myös kirjoittaa suoraan komentoriville muodossa
<syntaxhighlight lang="bash">
echo "Hei, `whoami`, mitä kuuluu"; echo "Olet hakemistossa $PWD, tiedostolistaus:"; ls;
</syntaxhighlight>


== Muuttujat ==
== Muuttujat ==
Muuttujat määritellään syntaksilla
Muuttujat määritellään syntaksilla
nimi=arvo
<syntaxhighlight lang="bash">
nimi=arvo
</syntaxhighlight>
ja niihin viitataan laittamalla muuttujan eteen $
ja niihin viitataan laittamalla muuttujan eteen $
$nimi
<syntaxhighlight lang="bash">
$nimi
</syntaxhighlight>
Siinä tapauksessa mikäli halutaan, että komennon tulos on muuttuja asetetaan muuttuja tyyliin:
<syntaxhighlight lang="bash">
nimi=("komennon nimi ja parametrit")
</syntaxhighlight>
Tapauksia, joissa käyttäjän tarkoittama muuttuja on epäselvä, tulee käyttää aaltosulkuja muuttujan ympärillä
Tapauksia, joissa käyttäjän tarkoittama muuttuja on epäselvä, tulee käyttää aaltosulkuja muuttujan ympärillä
${foo}bar
<syntaxhighlight lang="bash">
${foo}bar
</syntaxhighlight>
kun halutaan tulostaa teksti <tt>bar</tt> muuttujan <tt>foo</tt> jälkeen.
kun halutaan tulostaa teksti <tt>bar</tt> muuttujan <tt>foo</tt> jälkeen.


Ensimmäisen skriptimme tapauksessa käytimme jo ympäristömuuttujaa $PWD echo:n kanssa. Tehdäänpä samantyyppinen skripti nyt käyttäen itse määrittelemäämme muuttujaa:
Ensimmäisen skriptimme tapauksessa käytimme jo ympäristömuuttujaa $PWD echo:n kanssa. Tehdäänpä samantyyppinen skripti nyt käyttäen itse määrittelemäämme muuttujaa:
#!/bin/bash
<syntaxhighlight lang="bash">
HEI="Hei, `whoami`, mitä kuuluu?"
#!/bin/bash
echo $HEI
HEI="Hei, `whoami`, mitä kuuluu?"
echo $HEI
</syntaxhighlight>
Kuten huomaat, kun muuttujaan sijoitetaan arvo, voidaan käyttää samoja "kikkoja" kuin muuallakin skriptissä, esimerkiksi tässä tapauksessa sijoitamme muuttujaan merkkijonon jonka sisällä on ohjelman <tt>whoami</tt> tuloste.
Kuten huomaat, kun muuttujaan sijoitetaan arvo, voidaan käyttää samoja "kikkoja" kuin muuallakin skriptissä, esimerkiksi tässä tapauksessa sijoitamme muuttujaan merkkijonon jonka sisällä on ohjelman <tt>whoami</tt> tuloste.


Rivi 49: Rivi 71:
  MUUTTUJA= "moi"
  MUUTTUJA= "moi"
  MUUTTUJA ="moi"
  MUUTTUJA ="moi"
Lisäksi muuttujaan sijoitettavan arvon on oltava lainausmerkkien sisällä, jos siihen kuuluu välilyönti. Yksittäisen sanan tai numeron voi sijoittaa ilman lainausmerkkejä:
Lisäksi muuttujaan sijoitettavan arvon on oltava lainausmerkkien sisällä, jos siihen kuuluu välilyönti. Yksittäisen sanan tai numeron voi sijoittaa ilman lainausmerkkejä:
numero=43
<syntaxhighlight lang="bash">
numero=43
</syntaxhighlight>


== Ehtolauseet ==
== Ehtolauseet ==
Ehdollisia rakenteita luodaan bashille if, then, else ja fi -avainsanoilla. Rakenteen syntaksi on seuraava:
Ehdollisia rakenteita luodaan bashille if, then, else ja fi -avainsanoilla. Rakenteen syntaksi on seuraava:
if [ ehto ]
<syntaxhighlight lang="bash">
then
if [ ehto ]
then
     lauseita
     lauseita
elif [ toinen ehto ]
elif [ toinen ehto ]
then
then
     lauseita
     lauseita
else
else
     muita lauseita
     muita lauseita
fi
fi
</syntaxhighlight>


Ehdot merkitään hakasulkeiden sisään esimerkiksi seuraavalla tavalla
Ehdot merkitään hakasulkeiden sisään esimerkiksi seuraavalla tavalla
#!/bin/bash
<syntaxhighlight lang="bash">
if [ $PWD = "/" ]
#!/bin/bash
then
if [ $PWD = "/" ]
        echo "Tämä skripti suoritetaan juurihakemistossa";
then
else
    echo "Tämä skripti suoritetaan juurihakemistossa";
        echo "Skripti suoritetaan hakemistossa $PWD";
else
fi
    echo "Skripti suoritetaan hakemistossa $PWD";
fi
</syntaxhighlight>
 
=== Yhden rivin ehtolauseet ===
Lyhyiden skriptien kanssa.
<syntaxhighlight lang="bash">
[ ehto ] && lauseita || [ toinen ehto ] && lauseita || muita lauseita
 
[ $PWD = "/" ] && printf "\nTämä skripti suoritetaan juurihakemistossa\n" || printf "\nSkripti suoritetaan hakemistossa %s\n" "$PWD"
</syntaxhighlight>


Tässä käytetään vertailuoperaattoria =, joka on tosi, jos merkkijonot ovat samat. Muita vertailuoperaattoreita ovat
Tässä käytetään vertailuoperaattoria =, joka on tosi, jos merkkijonot ovat samat. Muita vertailuoperaattoreita ovat
Rivi 80: Rivi 117:
|-
|-
<!-- taulukko alkaa tästä -->
<!-- taulukko alkaa tästä -->
| !  || Negaatio-operaattori, "Onko seuraava ehto epätosi?"
|-
| -n || Pituus ei ole 0
| -n || Pituus ei ole 0
|-  
|-  
Rivi 112: Rivi 151:


Esimerkiksi seuraavat ehdot ovat tosia
Esimerkiksi seuraavat ehdot ovat tosia
[ 2 -lt 5 ]
<syntaxhighlight lang="bash">
[ "moi" != "linux" ]
[ 2 -lt 5 ]
[ 54 -ge 53 ]
[ "moi" != "linux" ]
[ -f "/etc/fstab" ]
[ 54 -ge 53 ]
[ -f "/etc/fstab" ]
</syntaxhighlight>


== Silmukat ==
== Silmukat ==
Rivi 121: Rivi 162:
For-silmukka on näppärä monessa tapauksessa, tässä esimerkkinä hakemiston kaikkien tiedostojen läpikäynti.
For-silmukka on näppärä monessa tapauksessa, tässä esimerkkinä hakemiston kaikkien tiedostojen läpikäynti.


for muuttuja in `ls`  
<syntaxhighlight lang="bash">
do
for muuttuja in `ls`  
  echo $muuttuja
do
done
    echo $muuttuja
Silmukassa suoritettavat rivit laitetaan siis sanojen <tt>do</tt> ja <tt>done</tt> väliin. Laskurimuuttujaan sijoitetaan vuorotellen <tt>in</tt>:n jälkeen olevat sanat, esimerkiksi tässä tapauksessa konennon [[ls]] tuloste (eli hakemistossa olevien tiedostojen nimet). Ohjelman tuloste voidaan merkitä myös seuraavasti: <tt>$(komento)</tt>. Jos silmukalla on käytävä läpi kaikki kokonaisluvut tietyltä väliltä, voi käyttää komentoa [[seq]], joka tulostaa kokonaisluvut väliltä 1-annettu parametri. Esimerkiksi
done
echo "Lasketaan kymmeneen:"
</syntaxhighlight>
for luku in $(seq 10)
Silmukassa suoritettavat rivit laitetaan siis sanojen <tt>do</tt> ja <tt>done</tt> väliin. Laskurimuuttujaan sijoitetaan vuorotellen <tt>in</tt>:n jälkeen olevat sanat, esimerkiksi tässä tapauksessa komennon [[ls]] tuloste (eli hakemistossa olevien tiedostojen nimet). Ohjelman tuloste voidaan merkitä myös seuraavasti: <tt>$(komento)</tt>. Jos silmukalla on käytävä läpi kaikki kokonaisluvut tietyltä väliltä, voi käyttää komentoa [[seq]], joka tulostaa kokonaisluvut väliltä 1-annettu parametri. Esimerkiksi
do
<syntaxhighlight lang="bash">
  echo $luku
echo "Lasketaan kymmeneen:"
done
for luku in $(seq 10)
do
    echo $luku
done
</syntaxhighlight>


Läpi käytävä joukko voidaan merkitä myös syntaksilla <tt>{alku..loppu}</tt>. Jos esimerkiksi halutaan käydä läpi kaikki merkit c-o, kokeile vaikka kirjoittaa
Läpi käytävä joukko voidaan merkitä myös syntaksilla <tt>{alku..loppu}</tt>. Jos esimerkiksi halutaan käydä läpi kaikki merkit c-o, kokeile vaikka kirjoittaa
for muuttuja in {c..o}; { echo -n "$muuttuja "; sleep 1;}
<syntaxhighlight lang="bash">for muuttuja in {c..o}; { echo -n "$muuttuja "; sleep 1;}</syntaxhighlight>
 
=== While ===
=== While ===
While suorittaa lausekkeita niin kauan kuin ehto on tosi. Kun ehto on epätosi poistutaan loopista joilloin skriptin suoritus jatkuu seuraavalta loogiselta riviltä (while-lausekkeen jälkseiseltä riviltä).
While suorittaa lausekkeita niin kauan kuin ehto on tosi. Kun ehto on epätosi poistutaan loopista jolloin skriptin suoritus jatkuu seuraavalta loogiselta riviltä (while-lausekkeen jälkeiseltä riviltä).
while [ ehto ]
<syntaxhighlight lang="bash">
do
while [ ehto ]
  lauseita
do
done
    lauseita
done


Esimerkki:
Esimerkki:
while [ -f "testi" ]
while [ -f "testi" ]
do
do
  echo "Tiedosto on olemassa."
    echo "Tiedosto on olemassa."
  [[sleep]] 1
    sleep 1
done
done
</syntaxhighlight>
Edellä oleva skripti tarkistaa, onko samassa hakemistossa oleva tiedosto <tt>testi</tt> olemassa. Tätä jatketaan niin kauan kunnes tiedostoa ei enää ole.
Edellä oleva skripti tarkistaa, onko samassa hakemistossa oleva tiedosto <tt>testi</tt> olemassa. Tätä jatketaan niin kauan kunnes tiedostoa ei enää ole.


=== Until ===
=== Until ===
Until on while:n vastakohta. Until-lauseke jatkaa suoritusta niin kauan kunnes ehto on tosi.  
Until on while:n vastakohta. Until-lauseke jatkaa suoritusta niin kauan kunnes ehto on tosi.  
until [ ehto ]
<syntaxhighlight lang="bash">
do
until [ ehto ]
  lauseita
do
done
    lauseita
done
</syntaxhighlight>
 
== Funktiot ==
== Funktiot ==
Kuten "oikeissa" ohjelmointikielissä, myös bash-skripteissä on mahdollista käyttää funktioita seuraavalla tavalla
Kuten "oikeissa" ohjelmointikielissä, myös bash-skripteissä on mahdollista käyttää funktioita seuraavalla tavalla
<pre>
 
<syntaxhighlight lang="bash">
#!/bin/bash
#!/bin/bash
function Käyttis {
function Käyttis {
Rivi 166: Rivi 218:
Käyttis
Käyttis
echo $os
echo $os
</pre>
</syntaxhighlight>
 
Tulostaisi "Linux".  
Tulostaisi "Linux".  


Funktio määritellään siis syntaksilla
Funktio määritellään siis syntaksilla
<pre>
<syntaxhighlight lang="bash">
 
function Funktio {
function Funktio {
  #koodi
  #koodi
}
}
</pre>
</syntaxhighlight>
Jos halutaan skriptin toimivan myös [[Sh]]-komentotulkkia käytettäessä, funktion kanssa on käytettävä syntaksia
Jos halutaan skriptin toimivan myös [[Sh]]-komentotulkkia käytettäessä, funktion kanssa on käytettävä syntaksia
<pre>
<syntaxhighlight lang="bash">
Funktio() { ... }
Funktio() { ... }
</pre>
</syntaxhighlight>


Jos muuttujia ei funktiossa erikseen määritellä yksityisiksi, ne ovat julkisia. Eli kun esimerkkiskriptissämme muutimme muuttujan $os arvoa funktiossa, tämä muutos näkyi myös funktion ulkopuolella. Muuttuja voidaan määritellä yksityiseksi avainsanalla <tt>local</tt>:
Jos muuttujia ei funktiossa erikseen määritellä yksityisiksi, ne ovat julkisia. Eli kun esimerkkiskriptissämme muutimme muuttujan $os arvoa funktiossa, tämä muutos näkyi myös funktion ulkopuolella. Muuttuja voidaan määritellä yksityiseksi avainsanalla <tt>local</tt>:
<pre>
 
<syntaxhighlight lang="bash">
#!/bin/bash
#!/bin/bash
function Käyttis {
function Käyttis {
Rivi 191: Rivi 246:
Käyttis
Käyttis
echo $os
echo $os
</pre>
</syntaxhighlight>
 
Tulostaisi "Debian".
Tulostaisi "Debian".


Rivi 210: Rivi 266:
Unixin filosofian mukaisesti Linuxissa on lukuisia ohjelmia, jotka hoitavat jonkin yksittäisen tehtävän ja tekevät sen hyvin. Näitä pikkuohjelmia käytetäänkin usein skripteissä hoitamaan erilaisia tehtäviä.
Unixin filosofian mukaisesti Linuxissa on lukuisia ohjelmia, jotka hoitavat jonkin yksittäisen tehtävän ja tekevät sen hyvin. Näitä pikkuohjelmia käytetäänkin usein skripteissä hoitamaan erilaisia tehtäviä.


Kaikista Linux-järjestelmistä löytyviä ohjelmia on listattu luokkaan [[:Luokka:Komentorivin perustyökalut|Komentorivin perustyökalut]]. Näitä ohjelmia kannattaa selailla. Komentoriviohjelmia on listattu käyttötarkoituksen mukaan myös artikkelissa [[komentorivikomennot]]
Kaikista Linux-järjestelmistä löytyviä ohjelmia on listattu luokkaan [[:Luokka:Komentorivin perustyökalut|Komentorivin perustyökalut]]. Näitä ohjelmia kannattaa selailla. Komentoriviohjelmia on listattu käyttötarkoituksen mukaan myös artikkelissa [[komentorivikomennot]].
 
Esimerkkinä ladataan kaikki [[LinuCast]]-podcastin [[ogg]]-muotoiset jaksot käyttämällä jokaisesta järjestelmästä löytyviä peruskomentoja [[seq]] ja [[wget]]:
 
(esimerkin sivusto on kuollut ja kuopattu, joten koodi ei toimi)
 
<syntaxhighlight lang="bash">
#!/bin/bash
# linucast.sh - LinuCast-podcastin latausskripti
for  i in `seq -f"%03g" 1 104`
do
    wget -c "http://koskisuomi.pp.fi/linucast/LinuCast$i.ogg"
done
</syntaxhighlight>
 
Esimerkkiohjelma voidaan tallentaa vaikka nimelle <tt>linuxcast.sh</tt> ja sille voidaan antaa [[chmod|suoritusoikeudet]] komennolla
chmod u+rx linucast.sh
Tämän jälkeen komentojono ajettaisiin komennolla
./linucast.sh
 
*1 tarkoittaa että mistä numerosta aloitetaan
*104 tarkoittaa kuinka monta jaksoa haetaan, lukua voi kasvattaa jaksojen lisääntyessä.
 
Esimerkki ohjelmana 2. Ladataan kaikki Full Circle magazinen englanninkieliset pdf-tiedostot palvelimelta. Esimerkissä on käytetty Bash skriptaus koodeja joita löytyy esimerkiksi tältä sivulta.
 
<syntaxhighlight lang="bash">
#!/bin/bash
# issueLataaja.sh - Ubuntu-aiheisen verkkojulkaisu Full Circle:n artikkelilataaja, kerää ne kaikki!
 
# Tyhjennetään ruutu
clear
 
# Haetaan kaikki Full Circlen artikkelit ensimmäisestä beta-julkaisusta (0) kaikkein uusimpaan asti.
 
# Listataan julkaisut verkkosivulta, joista viimeisin tallennetaan muuttujaksi.
viimeisin_julkaisu=$(curl -s https://fullcirclemagazine.org/downloads/ | grep -oP '(?<=Issue )[0-9]+' | tail -1);
 
for luku in $(seq 0 $viimeisin_julkaisu)
do
  FILE="issue"$luku"_en.pdf"
 
# Tarkistetaan onko tiedosto jo olemassa, ennen kuin ladataan se. 
if [ -f $FILE ]; then
  echo " '$FILE' tiedosto on olemassa."
else
  echo " '$FILE' tiedostoa ei ole olemassa. Ladataan se..."
  wget "https://dl.fullcirclemagazine.org/$FILE"
 
# Pidetään 5 sekunnin tauko latausten välissä, mukana laskuri
 
for (( i=5; i>0; i--)); do
    sleep 1 &
    printf "\b\b$i"   
    wait
done
fi
done
echo "Lataus valmis"
</syntaxhighlight>
 
Esimerkkiohjelma voidaan tallentaa vaikka nimelle <tt>issueLataaja.sh</tt> ja sille voidaan antaa [[chmod|suoritusoikeudet]] komennolla
chmod u+rx issueLataaja.sh
Tämän jälkeen komentojono ajettaisiin komennolla
./issueLataaja.sh


== Katso myös ==
== Katso myös ==
*[[Komentorivin perusteet]]
*[[Komentorivin perusteet]]
*[[Komentorivivinkkejä]]
*[[Komentorivivinkkejä]]
*[[ShellCheck]] on ohjelma, joka havaitsee kaikki [[sh]] ja [[bash]]-skriptien ongelmat ja antaa niille parannusehdotukset.


==Aiheesta muualla==
==Aiheesta muualla==
*[http://tldp.org/LDP/abs/html/ Advanced Bash-Scripting Guide] - laaja englanninkielinen opas bash-skriptaukseen
*[https://tldp.org/LDP/abs/html/ Advanced Bash-Scripting Guide] - laaja englanninkielinen opas bash-skriptaukseen
*[http://www.panix.com/~elflord/unix/bash-tute.html Pikaopas bash-skriptaukseen] (englanniksi)
*[https://www.panix.com/~elflord/unix/bash-tute.html Pikaopas bash-skriptaukseen] (englanniksi)
*[https://web.archive.org/web/20170610153335/https://gd.tuwien.ac.at/linuxcommand.org/writing_shell_scripts.php Writing shell scripts] - toinen laaja englanninkielinen opas bash-skriptaukseen - archive.org tallenne 10.6.2017
*[https://www.shellcheck.net/ ShellCheck] on www-ohjelma, joka havaitsee kaikki [[sh]] ja [[bash]]-skriptien ongelmat ja antaa niille parannusehdotukset.
*[https://explainshell.com/ ExplainShell] on www-ohjelma, joka antaa ohjetekstin annetuille komennoille.
*[https://mywiki.wooledge.org/BashPitfalls Bash Pitfalls] yleisimmät bash-skriptauksen sudenkuopat.
 




[[Luokka:Komentorivi]]
[[Luokka:Komentorivi]]
[[Luokka:Ohjeet]]
[[Luokka:Ohjeet]]
3 173

muokkausta

Navigointivalikko