Bash/Kontrollstrukturen: Unterschied zwischen den Versionen

Aus Foxwiki
Die Seite wurde neu angelegt: „= {{anchor|RefHeadingToc25752005955943}} Kontrollstrukturen = Bei der Shell-Programmierung verfügt man über ähnliche Konstrukte wie bei anderen Programmier…“
 
KKeine Bearbeitungszusammenfassung
Zeile 1: Zeile 1:
= {{anchor|RefHeadingToc25752005955943}} Kontrollstrukturen =
= Kontrollstrukturen =
 
Bei der Shell-Programmierung verfügt man über ähnliche Konstrukte wie bei anderen Programmiersprachen, um den Ablauf des Programms zu steuern. Dazu gehören bedingte Verzweigungen, Schleifen und Fallunterscheidungen.
Bei der Shell-Programmierung verfügt man über ähnliche Konstrukte wie bei anderen Programmiersprachen, um den Ablauf des Programms zu steuern. Dazu gehören bedingte Verzweigungen, Schleifen und Fallunterscheidungen.


== Bedingungen testen ==
== Bedingungen testen ==
Das wichtigste Kommando ist 'test', mit dem man mannigfache Bedingungen testen kann.  
Das wichtigste Kommando ist 'test', mit dem man mannigfache Bedingungen testen kann.  


<div style="margin-left:0cm;margin-right:0cm;">test Argument </div>
test Argument  


Dieses Kommando prüft eine Bedingung und liefert 'true' (0), falls die Bedingung erfüllt ist und 'false' (1), falls die Bedingung nicht erfüllt ist. Der Fehlerwert 2 wird zurückgegeben, wenn das Argument syntaktisch falsch ist (meist durch Ersetzung hervorgerufen).  
Dieses Kommando prüft eine Bedingung und liefert 'true' (0), falls die Bedingung erfüllt ist und 'false' (1), falls die Bedingung nicht erfüllt ist. Der Fehlerwert 2 wird zurückgegeben, wenn das Argument syntaktisch falsch ist (meist durch Ersetzung hervorgerufen).  
Zeile 15: Zeile 13:
In bestimmten Fällen können auf der rechten Seite eines Vergleichs auch Strings oder Zahlen stehen - bei der Ersetzung von leeren Variablen kann es aber zu Syntaxfehlern kommen. Weiterhin lassen sich mehrere Argumente logisch verknüpfen (UND, ODER, NICHT). Beispiel:  
In bestimmten Fällen können auf der rechten Seite eines Vergleichs auch Strings oder Zahlen stehen - bei der Ersetzung von leeren Variablen kann es aber zu Syntaxfehlern kommen. Weiterhin lassen sich mehrere Argumente logisch verknüpfen (UND, ODER, NICHT). Beispiel:  


<div style="margin-left:0cm;margin-right:0cm;">test -w /etc/passwd </div>
test -w /etc/passwd  


mit der Kommandoverkettung lassen sich so schon logische Entscheidungen treffen, z. B.:  
mit der Kommandoverkettung lassen sich so schon logische Entscheidungen treffen, z. B.:  


<div style="margin-left:0cm;margin-right:0cm;">test -w /etc/passwd && echo "Du bist ROOT" </div>
test -w /etc/passwd && echo "Du bist ROOT"  


Normalerweise kann statt 'test' das Argument auch in eckigen Klammern gesetzt werden. Die Klammern müssen von Leerzeichen umschlossen werden:  
Normalerweise kann statt 'test' das Argument auch in eckigen Klammern gesetzt werden. Die Klammern müssen von Leerzeichen umschlossen werden:  


<div style="margin-left:0cm;margin-right:0cm;">[ -w /etc/passwd ] </div>
[ -w /etc/passwd ]  


Die folgenden Operationen können bei 'test' bzw. [ ... ] verwendet werden.  
Die folgenden Operationen können bei 'test' bzw. [ ... ] verwendet werden.  




{| align="center" style="border-spacing:0;width:17.501cm;"
{|  
|- style="border-top:2.5pt solid #000000;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;"
|-  
| colspan="2" | '''Dateitests: '''
| colspan="2" | '''Dateitests: '''
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-b Datei '''</tt>
| | <tt>'''-b Datei '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Datei existiert und ist ein blockorientiertes Gerät  
| | Die Datei existiert und ist ein blockorientiertes Gerät  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-c Datei '''</tt>
| | <tt>'''-c Datei '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Datei existiert und ist ein zeichenorientiertes Gerät  
| | Die Datei existiert und ist ein zeichenorientiertes Gerät  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-d Datei '''</tt>
| | <tt>'''-d Datei '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Datei existiert und ist ein Verzeichnis  
| | Die Datei existiert und ist ein Verzeichnis  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-e Datei'''</tt>
| | <tt>'''-e Datei'''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Datei existiert
| | Datei existiert
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-f Datei '''</tt>
| | <tt>'''-f Datei '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Datei existiert und ist eine reguläre Datei  
| | Die Datei existiert und ist eine reguläre Datei  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-g Datei '''</tt>
| | <tt>'''-g Datei '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Datei existiert und das Gruppen-ID-Bit ist gesetzt  
| | Die Datei existiert und das Gruppen-ID-Bit ist gesetzt  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-h Datei '''</tt>
| | <tt>'''-h Datei '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Datei existiert und ist ein symbolischer Link  
| | Die Datei existiert und ist ein symbolischer Link  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-k Datei '''</tt>
| | <tt>'''-k Datei '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Datei existiert und das Sticky-Bit ist gesetzt  
| | Die Datei existiert und das Sticky-Bit ist gesetzt  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-p Datei '''</tt>
| | <tt>'''-p Datei '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Datei existiert und ist eine Named Pipe  
| | Die Datei existiert und ist eine Named Pipe  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-r Datei '''</tt>
| | <tt>'''-r Datei '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Datei existiert und ist lesbar  
| | Die Datei existiert und ist lesbar  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-s Datei '''</tt>
| | <tt>'''-s Datei '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Datei existiert und ist nicht leer  
| | Die Datei existiert und ist nicht leer  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-t [n] '''</tt>
| | <tt>'''-t [n] '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | DATEI-Descriptor FD (Standard: Standardausgabe) ist auf Tty offen
| | DATEI-Descriptor FD (Standard: Standardausgabe) ist auf Tty offen
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-u Datei '''</tt>
| | <tt>'''-u Datei '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Datei existiert und das Setuid-Bit ist gesetzt  
| | Die Datei existiert und das Setuid-Bit ist gesetzt  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-w Datei '''</tt>
| | <tt>'''-w Datei '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Datei existiert und ist beschreibbar  
| | Die Datei existiert und ist beschreibbar  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-x Datei '''</tt>
| | <tt>'''-x Datei '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Datei existiert und ist ausführbar  
| | Die Datei existiert und ist ausführbar  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Datei1 -nt Datei2
| | Datei1 -nt Datei2
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Datei1 ist neuer als Datei2
| | Datei1 ist neuer als Datei2
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Datei1 -ot Datei2
| | Datei1 -ot Datei2
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Datei1 ist älter als Datei2
| | Datei1 ist älter als Datei2
|-
|-
| style="border-top:none;border-bottom:2.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Datei1 -ef Datei2
| | Datei1 -ef Datei2
| style="border-top:none;border-bottom:2.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Beide Dateien belegen dieselbe Inode auf demselben Gerät
| | Beide Dateien belegen dieselbe Inode auf demselben Gerät
|-
|-
|}
|}
'''Beispiel'''
'''Beispiel'''


<div style="margin-left:0cm;margin-right:0cm;">if [ -d RCS ]    Wenn ein Verzeichnis RCS existiert. . .</div>
if [ -d RCS ]    Wenn ein Verzeichnis RCS existiert. . .




{| align="center" style="border-spacing:0;width:17.501cm;"
{|  
|- style="border-top:2.5pt solid #000000;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;"
|-  
| colspan="2" | '''Bedingungen für Zeichenfolgen: '''
| colspan="2" | '''Bedingungen für Zeichenfolgen: '''
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-n s1 '''</tt>
| | <tt>'''-n s1 '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Länge der Zeichenfolge s1 ist ungleich Null  
| | Die Länge der Zeichenfolge s1 ist ungleich Null  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''-z s1 '''</tt>
| | <tt>'''-z s1 '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Länge der Zeichenfolge s1 ist gleich Null  
| | Die Länge der Zeichenfolge s1 ist gleich Null  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''s1 = s2 '''</tt>
| | <tt>'''s1 = s2 '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Zeichenfolgen s1 und s2 sind identisch  
| | Die Zeichenfolgen s1 und s2 sind identisch  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''s1 != s2 '''</tt>
| | <tt>'''s1 != s2 '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Zeichenfolgen s1 und s2 sind nicht identisch  
| | Die Zeichenfolgen s1 und s2 sind nicht identisch  
|-
|-
| style="border-top:none;border-bottom:2.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''Zeichenfolge '''</tt>
| | <tt>'''Zeichenfolge '''</tt>
| style="border-top:none;border-bottom:2.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Die Zeichenfolge ist nicht Null  
| | Die Zeichenfolge ist nicht Null  
|-
|-
|}
|}
'''Beispiel'''
'''Beispiel'''


<div style="margin-left:0cm;margin-right:0cm;">if [ "$Antwort" != "j" ]    Wenn die $Antwort nicht "j" ist. . .</div>
if [ "$Antwort" != "j" ]    Wenn die $Antwort nicht "j" ist. . .


 
{|  
 
|-  
{| align="center" style="border-spacing:0;width:17.501cm;"
|- style="border-top:2.5pt solid #000000;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;"
| colspan="2" | '''Ganzzahlvergleiche: '''
| colspan="2" | '''Ganzzahlvergleiche: '''
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''n1 -eq n2 '''</tt>
| | <tt>'''n1 -eq n2 '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | n1 ist gleich n2  
| | n1 ist gleich n2  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''n1 -ge n2 '''</tt>
| | <tt>'''n1 -ge n2 '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | n1 ist größer oder gleich n2  
| | n1 ist größer oder gleich n2  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''n1 -gt n2 '''</tt>
| | <tt>'''n1 -gt n2 '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | n1 ist größer als n2  
| | n1 ist größer als n2  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''n1 -le n2 '''</tt>
| | <tt>'''n1 -le n2 '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | n1 ist kleiner oder gleich n2  
| | n1 ist kleiner oder gleich n2  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''n1 -lt n2 '''</tt>
| | <tt>'''n1 -lt n2 '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | n1 ist kleiner n2  
| | n1 ist kleiner n2  
|-
|-
| style="border-top:none;border-bottom:2.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''n1 -ne n2 '''</tt>
| | <tt>'''n1 -ne n2 '''</tt>
| style="border-top:none;border-bottom:2.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | n1 ist ungleich n2  
| | n1 ist ungleich n2  
|-
|-
|}
|}
'''Beispiele'''
'''Beispiele'''


<div style="margin-left:0cm;margin-right:0cm;">while test $# -gt 0    Solange Argumente vorliegen. . .
while test $# -gt 0    Solange Argumente vorliegen. . .
   
   
  while [ -n "$1" ]    Solange das erste Argument nicht leer ist. . .
  while [ -n "$1" ]    Solange das erste Argument nicht leer ist. . .
   
   
  if [ $count -lt 10 ]    Wenn $count kleiner 10. . .</div>
  if [ $count -lt 10 ]    Wenn $count kleiner 10. . .
 


{| align="center" style="border-spacing:0;width:17.501cm;"
{|  
|- style="border-top:2.5pt solid #000000;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;"
|-  
| colspan="2" | '''Kombinierte Formen: '''
| colspan="2" | '''Kombinierte Formen: '''
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''(Bedingung) '''</tt>
| | <tt>'''(Bedingung) '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Wahr, wenn die Bedingung zutrifft (wird für die Gruppierung verwendet). Den Klammern muss ein \ vorangestellt werden.
| | Wahr, wenn die Bedingung zutrifft (wird für die Gruppierung verwendet). Den Klammern muss ein \ vorangestellt werden.
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''! Bedingung i '''</tt>
| | <tt>'''! Bedingung i '''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Wahr, wenn die Bedingung nicht zutrifft (NOT).  
| | Wahr, wenn die Bedingung nicht zutrifft (NOT).  
|-
|-
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''Bedingung1 -a Bedingung2'''</tt>
| | <tt>'''Bedingung1 -a Bedingung2'''</tt>
| style="border-top:none;border-bottom:0.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Wahr, wenn beide Bedingungen zutreffen (AND).
| | Wahr, wenn beide Bedingungen zutreffen (AND).
|-
|-
| style="border-top:none;border-bottom:2.5pt solid #000000;border-left:2.5pt solid #000000;border-right:none;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | <tt>'''Bedingung1 -o Bedingung2'''</tt>
| | <tt>'''Bedingung1 -o Bedingung2'''</tt>
| style="border-top:none;border-bottom:2.5pt solid #000000;border-left:0.5pt solid #000000;border-right:2.5pt solid #000000;padding-top:0.049cm;padding-bottom:0.049cm;padding-left:0.3cm;padding-right:0.3cm;" | Wahr, wenn eine der beiden Bedingungen zutrifft (OR).
| | Wahr, wenn eine der beiden Bedingungen zutrifft (OR).
|-
|-
|}
|}
'''Beispiel'''
'''Beispiel'''


<div style="margin-left:0cm;margin-right:0cm;">if [ ! -r "$1" -o ! -f "$1" ]    Wenn das erste Argument keine lesbare oder reguläre Datei ist.</div>
if [ ! -r "$1" -o ! -f "$1" ]    Wenn das erste Argument keine lesbare oder reguläre Datei ist.


== Bedingte Anweisung (if - then - else) ==
== Bedingte Anweisung (if - then - else) ==
Wichtig: Als Bedingung kann nicht nur der test-Befehl, sondern eine beliebige Folge von Kommados verwendet werden.  
Wichtig: Als Bedingung kann nicht nur der test-Befehl, sondern eine beliebige Folge von Kommados verwendet werden.  


Zeile 188: Zeile 183:


=== if ===
=== if ===
Die if-Anweisung in der Shell-Programmierung macht das gleiche wie in allen anderen Programmiersprachen, sie testet eine Bedingung auf Wahrheit und macht davon den weiteren Ablauf des Programms abhängig.  
Die if-Anweisung in der Shell-Programmierung macht das gleiche wie in allen anderen Programmiersprachen, sie testet eine Bedingung auf Wahrheit und macht davon den weiteren Ablauf des Programms abhängig.  


Die Syntax der if-Anweisung lautet wie folgt:  
Die Syntax der if-Anweisung lautet wie folgt:  


<div style="margin-left:0cm;margin-right:0cm;">if Bedingung1
if Bedingung1
     then Befehle1
     then Befehle1
  [ elif Bedingung2
  [ elif Bedingung2
Zeile 199: Zeile 193:
  ...
  ...
  [ else Befehle3 ]
  [ else Befehle3 ]
  fi</div>
  fi


Wenn die Bedingung1 erfüllt ist, werden die Befehle1 ausgeführt; andernfalls, wenn die Bedingung2 erfüllt ist, werden die Befehle2 ausgeführt. Trifft keine Bedingung zu, sollen die Befehle3 ausgeführt werden.  
Wenn die Bedingung1 erfüllt ist, werden die Befehle1 ausgeführt; andernfalls, wenn die Bedingung2 erfüllt ist, werden die Befehle2 ausgeführt. Trifft keine Bedingung zu, sollen die Befehle3 ausgeführt werden.  
Zeile 209: Zeile 203:
Man achte auf die Positionierung der Semikoli.  
Man achte auf die Positionierung der Semikoli.  


<div style="margin-left:0cm;margin-right:0cm;"><nowiki>#!/bin/sh</nowiki>
#!/bin/sh
<nowiki># Füge eine 0 vor Zahlen kleiner 10 ein:</nowiki>
  # Füge eine 0 vor Zahlen kleiner 10 ein:
  counter=0
  counter=0
  if [ $counter -lt 10 ]; then
  if [ $counter -lt 10 ]; then
   
   
  number=0$counter; else number=$counter; fi</div>
  number=0$counter; else number=$counter; fi
<div style="margin-left:0cm;margin-right:0cm;"><nowiki>#!/bin/bash</nowiki>
#!/bin/bash
<nowiki># Erstelle ein Verzeichnis, wenn es noch nicht existiert:</nowiki>
  # Erstelle ein Verzeichnis, wenn es noch nicht existiert:
  dir=daten
  dir=daten
  if [ ! -e $dir ]; then
  if [ ! -e $dir ]; then
  mkdir $dir; fi # mkdir: Verzeichnis erstellen</div>
  mkdir $dir; fi # mkdir: Verzeichnis erstellen


=== einseitiges if ===
=== einseitiges if ===
 
if kommandoliste  
<div style="margin-left:0cm;margin-right:0cm;">if kommandoliste  
  then  
  then  
       kommandos  
       kommandos  
  fi </div>
  fi  


=== zweiseitiges if ===
=== zweiseitiges if ===
 
if kommandoliste  
<div style="margin-left:0cm;margin-right:0cm;">if kommandoliste  
  then  
  then  
       kommandos  
       kommandos  
  else  
  else  
       kommandos  
       kommandos  
  fi </div>
  fi  


=== Mehrstufiges if ===
=== Mehrstufiges if ===
 
if kommandoliste1  
<div style="margin-left:0cm;margin-right:0cm;">if kommandoliste1  
  then  
  then  
       kommandos
       kommandos
Zeile 247: Zeile 238:
  elif ...  
  elif ...  
           ...  
           ...  
  fi </div>
  fi  


=== Beispiele ===
=== Beispiele ===
<u>Es soll eine Meldung ausgegeben werden, falls mehr als 5 Benutzer eingeloggt sind: </u>
<u>Es soll eine Meldung ausgegeben werden, falls mehr als 5 Benutzer eingeloggt sind: </u>


<div style="margin-left:0cm;margin-right:0cm;">USERS=`who | wc -l` <nowiki># Zeilen der who-Ausgabe zählen</nowiki>
USERS=`who | wc -l`   # Zeilen der who-Ausgabe zählen
  if test $USERS -gt 5  
  if test $USERS -gt 5  
  then  
  then  
   echo "Mehr als 5 Benutzer am Geraet"  
   echo "Mehr als 5 Benutzer am Geraet"  
  fi </div>
  fi  


<u>Das geht natürlich auch kürzer und ohne Backtics: </u>
<u>Das geht natürlich auch kürzer und ohne Backtics: </u>


<div style="margin-left:0cm;margin-right:0cm;">if [ $(who | wc -l) -gt 5 ] ; then  
if [ $(who | wc -l) -gt 5 ] ; then  
   echo "Mehr als 5 Benutzer am Geraet"  
   echo "Mehr als 5 Benutzer am Geraet"  
  fi </div>
  fi  


Man sollte bei der Entwicklung von Skripts aber ruhig mit der Langfassung beginnen und sich erst der Kurzfassung zuwenden, wenn man mehr Übung hat und die Langfassungen auf Anhieb funktionieren.  
Man sollte bei der Entwicklung von Skripts aber ruhig mit der Langfassung beginnen und sich erst der Kurzfassung zuwenden, wenn man mehr Übung hat und die Langfassungen auf Anhieb funktionieren.  
Zeile 269: Zeile 259:
<u>Ein weiteres Beispiel zeigt eine Fehlerprüfung: </u>
<u>Ein weiteres Beispiel zeigt eine Fehlerprüfung: </u>


<div style="margin-left:0cm;margin-right:0cm;">if test $# -eq 0  
if test $# -eq 0  
  then  
  then  
   echo "usage: sortiere filename" >&2  
   echo "usage: sortiere filename" >&2  
  else  
  else  
   sort +1 -2 $1 | lp  
   sort +1 -2 $1 | lp  
  fi </div>
  fi  


Das nächste Beispiel zeigt eine mehr oder weniger intelligente Anzeige für Dateien und Verzeichnisse. 'show' zeigt bei Dateien den Inhalt mit 'less' an und Verzeichnisse werden mit 'ls' präsentiert.  
Das nächste Beispiel zeigt eine mehr oder weniger intelligente Anzeige für Dateien und Verzeichnisse. 'show' zeigt bei Dateien den Inhalt mit 'less' an und Verzeichnisse werden mit 'ls' präsentiert.  
Zeile 280: Zeile 270:
<u>Fehlt der Parameter, wird interaktiv nachgefragt: </u>
<u>Fehlt der Parameter, wird interaktiv nachgefragt: </u>


<div style="margin-left:0cm;margin-right:0cm;">if [ $# -eq 0 ]                         <nowiki># falls keine Angabe </nowiki>
if [ $# -eq 0 ]                           # falls keine Angabe  
  then                                     <nowiki># interaktiv erfragen </nowiki>
  then                                     # interaktiv erfragen  
     echo -n "Bitte Namen eingeben: "
     echo -n "Bitte Namen eingeben: "
     read DATEI  
     read DATEI  
Zeile 287: Zeile 277:
     DATEI=$1  
     DATEI=$1  
  fi
  fi
  if  [ -f $DATEI ]                         <nowiki># wenn normale Datei </nowiki>
  if  [ -f $DATEI ]                         # wenn normale Datei  
  then                                     <nowiki># dann ausgeben </nowiki>
  then                                     # dann ausgeben  
     less $DATEI   
     less $DATEI   
  elif [ -d $DATEI ]                       <nowiki># wenn aber Verzeichnis </nowiki>
  elif [ -d $DATEI ]                       # wenn aber Verzeichnis  
   then                                   <nowiki># dann Dateien zeigen </nowiki>
   then                                   # dann Dateien zeigen  
       ls -CF $DATEI  
       ls -CF $DATEI  
     else                                 <nowiki># sonst Fehlermeldung </nowiki>
     else                                   # sonst Fehlermeldung  
       echo "cannot show $DATEI"   
       echo "cannot show $DATEI"   
  fi</div>
  fi


Das nächste Beispiel hängt eine Datei an eine andere Datei an; vorher erfolgt eine Prüfung der Zugriffsberechtigungen:  
Das nächste Beispiel hängt eine Datei an eine andere Datei an; vorher erfolgt eine Prüfung der Zugriffsberechtigungen:  
Zeile 301: Zeile 291:
<tt>append Datei1 Datei2</tt>  
<tt>append Datei1 Datei2</tt>  


<div style="margin-left:0cm;margin-right:0cm;">if [ -r $1 -a -w $2 ]  
if [ -r $1 -a -w $2 ]  
  then  
  then  
     cat $1 >> $2  
     cat $1 >> $2  
  else  
  else  
     echo "cannot append"  
     echo "cannot append"  
  fi </div>
  fi  


Beim Vergleich von Zeichenketten sollten möglichst die Anführungszeichen (" ... ") verwendet werden, da sonst bei der Ersetzung durch die Shell unvollständige Test-Kommandos entstehen können.  
Beim Vergleich von Zeichenketten sollten möglichst die Anführungszeichen (" ... ") verwendet werden, da sonst bei der Ersetzung durch die Shell unvollständige Test-Kommandos entstehen können.  
Zeile 312: Zeile 302:
Dazu ein Beispiel:  
Dazu ein Beispiel:  


<div style="margin-left:0cm;margin-right:0cm;">if [ ! -n $1 ] ; then  
if [ ! -n $1 ] ; then  
     echo "Kein Parameter"  
     echo "Kein Parameter"  
  fi </div>
  fi  


Ist $1 wirklich nicht angegeben, wird das Kommando reduziert zu:  
Ist $1 wirklich nicht angegeben, wird das Kommando reduziert zu:  


<div style="margin-left:0cm;margin-right:0cm;">if [ ! -n ] ; then .... </div>
if [ ! -n ] ; then ....  


Es ist also unvollständig und es erfolgt eine Fehlermeldung. Dagegen liefert  
Es ist also unvollständig und es erfolgt eine Fehlermeldung. Dagegen liefert  


<div style="margin-left:0cm;margin-right:0cm;">if [ ! -n "$1" ] ; then  
if [ ! -n "$1" ] ; then  
     echo "Kein Parameter"  
     echo "Kein Parameter"  
  fi </div>
  fi  


bei fehlendem Parameter den korrekten Befehl  
bei fehlendem Parameter den korrekten Befehl  


<div style="margin-left:0cm;margin-right:0cm;">if [ ! -n "" ] </div>
if [ ! -n "" ]  


Bei fehlenden Anführungszeichen werden auch führende Leerzeichen der Variablenwerte oder Parameter eliminiert.  
Bei fehlenden Anführungszeichen werden auch führende Leerzeichen der Variablenwerte oder Parameter eliminiert.  
Zeile 336: Zeile 326:
Es kommt ab und zu vor, dass eine Userid wechselt oder dass die Gruppenzugehörigkeit von Dateien geändert werden muss. In solchen fällen helfen die beiden folgenden Skripts:  
Es kommt ab und zu vor, dass eine Userid wechselt oder dass die Gruppenzugehörigkeit von Dateien geändert werden muss. In solchen fällen helfen die beiden folgenden Skripts:  


<div style="margin-left:0cm;margin-right:0cm;"><nowiki>#!/bin/sh</nowiki>
#!/bin/sh
<nowiki># Change user-id</nowiki>
  # Change user-id
<nowiki>#</nowiki>
  #
  if [ $# -ne 2 ] ; then
  if [ $# -ne 2 ] ; then
   echo "usage `basename $0` <old id> <new id>"
   echo "usage `basename $0` <old id> <new id>"
   exit
   exit
  fi
  fi
  find ~ -user $1 -exec chown $2 {} ";"</div>
  find ~ -user $1 -exec chown $2 {} ";"
<div style="margin-left:0cm;margin-right:0cm;"><nowiki>#!/bin/sh</nowiki>
#!/bin/sh
<nowiki># Change group-id</nowiki>
  # Change group-id
<nowiki>#</nowiki>
  #
  if [ $# -ne 2 ] ; then
  if [ $# -ne 2 ] ; then
   echo "usage `basename $0` <old id> <new id>"
   echo "usage `basename $0` <old id> <new id>"
   exit
   exit
  fi
  fi
  find / -group $1 -exec chgrp $2 {} ";"</div>
  find / -group $1 -exec chgrp $2 {} ";"


== case ==
== case ==
Auch die case-Anweisung ist vergleichbar in vielen anderen Sprachen vorhanden.  
Auch die case-Anweisung ist vergleichbar in vielen anderen Sprachen vorhanden.  


Zeile 363: Zeile 352:
Die Syntax der case-Anweisung lautet wie folgt:  
Die Syntax der case-Anweisung lautet wie folgt:  


<div style="margin-left:0cm;margin-right:0cm;">case Wert in
case Wert in
     Muster1) Befehle1;;
     Muster1) Befehle1;;
     Muster2) Befehle2;;
     Muster2) Befehle2;;
  ...
  ...
   
   
  esac</div>
  esac


Wenn der Wert mit dem Muster1 übereinstimmt, wird die entsprechende Befehlsgruppe (Befehle1) ausgeführt, bei Übereinstimmung mit Muster2 werden die Kommandos der zweiten Befehlsgruppe (Befehle2) ausgeführt, usw.  
Wenn der Wert mit dem Muster1 übereinstimmt, wird die entsprechende Befehlsgruppe (Befehle1) ausgeführt, bei Übereinstimmung mit Muster2 werden die Kommandos der zweiten Befehlsgruppe (Befehle2) ausgeführt, usw.  
Zeile 382: Zeile 371:
'''Beispiele'''
'''Beispiele'''


<div style="margin-left:0cm;margin-right:0cm;"><nowiki>#!/bin/sh</nowiki>
#!/bin/sh
<nowiki># Mit dem ersten Argument in der Befehlszeile </nowiki>
  # Mit dem ersten Argument in der Befehlszeile  
<nowiki># wird die entsprechende Aktion festgelegt:</nowiki>
  # wird die entsprechende Aktion festgelegt:
   
   
  case $1 in # nimmt das erste Argument
  case $1 in # nimmt das erste Argument
       Ja|Nein) response=1;;
       Ja|Nein) response=1;;
            <nowiki>*) echo "Unbekannte Option"; exit 1;;</nowiki>
            *) echo "Unbekannte Option"; exit 1;;
  esac</div>
  esac




<div style="margin-left:0cm;margin-right:0cm;"><nowiki>#!/bin/sh</nowiki>
#!/bin/sh
<nowiki># Lies die Zeilen von der Standardeingabe, bis eine</nowiki>
  # Lies die Zeilen von der Standardeingabe, bis eine
<nowiki># Zeile mit einem einzelnen Punkt eingegeben wird:</nowiki>
  # Zeile mit einem einzelnen Punkt eingegeben wird:
  while : # Null-Befehl
  while : # Null-Befehl
  do
  do
Zeile 402: Zeile 391:
           .) echo "Ausgefuehrt"
           .) echo "Ausgefuehrt"
             break;;
             break;;
          <nowiki>*) echo "$line" >>./message ;;</nowiki>
          *) echo "$line" >>./message ;;
     esac
     esac
  done</div>
  done


'''case-Anweisung'''
'''case-Anweisung'''
Zeile 410: Zeile 399:
Diese Anweisung erlaubt eine Mehrfachauswahl. Sie wird auch gerne deshalb verwendet, weil sie Muster mit Jokerzeichen und mehrere Muster für eine Auswahl erlauben  
Diese Anweisung erlaubt eine Mehrfachauswahl. Sie wird auch gerne deshalb verwendet, weil sie Muster mit Jokerzeichen und mehrere Muster für eine Auswahl erlauben  


<div style="margin-left:0cm;margin-right:0cm;">case selector in  
case selector in  
       Muster-1) Kommandofolge 1 ;;  
       Muster-1) Kommandofolge 1 ;;  
       Muster-2) Kommandofolge 2 ;;  
       Muster-2) Kommandofolge 2 ;;  
Zeile 416: Zeile 405:
   
   
       Muster-n) Kommandofolge n ;;  
       Muster-n) Kommandofolge n ;;  
  esac </div>
  esac  


Die Variable <tt>selector</tt> (String) wird der Reihe nach mit den Mustern "Muster-1" bis "Muster-n" verglichen. Bei Gleichheit wird die nachfolgende Kommandofolge ausgeführt und dann nach der case-Anweisung (also hinter dem <tt>esac</tt>) fortgefahren. * In den Mustern sind Metazeichen (*, ?, []) erlaubt, im Selektor dagegen nicht.  
Die Variable <tt>selector</tt> (String) wird der Reihe nach mit den Mustern "Muster-1" bis "Muster-n" verglichen. Bei Gleichheit wird die nachfolgende Kommandofolge ausgeführt und dann nach der case-Anweisung (also hinter dem <tt>esac</tt>) fortgefahren. * In den Mustern sind Metazeichen (*, ?, []) erlaubt, im Selektor dagegen nicht.  
Zeile 422: Zeile 411:
* Vor der Klammer können mehrere Muster, getrennt durch <tt>| </tt>stehen. Das Zeichen <tt>| </tt>bildet eine Oder-Bedingung:  
* Vor der Klammer können mehrere Muster, getrennt durch <tt>| </tt>stehen. Das Zeichen <tt>| </tt>bildet eine Oder-Bedingung:  


<div style="margin-left:0cm;margin-right:0cm;">case selector in  
case selector in  
       Muster1)              Kommandofolge1 ;;  
       Muster1)              Kommandofolge1 ;;  
       Muster2 | Muster3)    Kommandofolge2 ;;  
       Muster2 | Muster3)    Kommandofolge2 ;;  
      <nowiki>*) </nowiki>                  Kommandofolge3 ;;  
      *)                   Kommandofolge3 ;;  
  esac</div><u>Beispiel 1: Automatische Bearbeitung von Quell- und Objekt-Dateien. Der Aufruf erfolgt mit 'compile Datei'. </u>
  esac<u>Beispiel 1: Automatische Bearbeitung von Quell- und Objekt-Dateien. Der Aufruf erfolgt mit 'compile Datei'. </u>


<div style="margin-left:0cm;margin-right:0cm;">case $1 in  
case $1 in  
    <nowiki>*.s) as $1 ;; </nowiki>                      <nowiki># Assembler aufrufen </nowiki>
    *.s) as $1 ;;                       # Assembler aufrufen  
    <nowiki>*.c) cc -c $1 ;; </nowiki>                  <nowiki># C-Compiler aufrufen </nowiki>
    *.c) cc -c $1 ;;                     # C-Compiler aufrufen  
    <nowiki>*.o) cc $1 -o prog ;; </nowiki>              <nowiki># C-Compiler als Linker </nowiki>
    *.o) cc $1 -o prog ;;               # C-Compiler als Linker  
      <nowiki>*) echo "invalid parameter: $1";; </nowiki>
      *) echo "invalid parameter: $1";;  
  esac</div>
  esac


<u>Beispiel 2: Menü mit interaktiver Eingabe</u>
<u>Beispiel 2: Menü mit interaktiver Eingabe</u>


<div style="margin-left:0cm;margin-right:0cm;">while : <nowiki># Endlosschleife (s. später) </nowiki>
while :   # Endlosschleife (s. später)  
  do  
  do  
  tput clear <nowiki># Schirm löschen und Menütext ausgeben </nowiki>
  tput clear   # Schirm löschen und Menütext ausgeben  
     echo " +---------------------------------+"   
     echo " +---------------------------------+"   
     echo " | 0 --> Ende                      |"  
     echo " | 0 --> Ende                      |"  
Zeile 447: Zeile 436:
     echo " | 4 --> Mail                      |"  
     echo " | 4 --> Mail                      |"  
     echo "+----------------------------------+"  
     echo "+----------------------------------+"  
     echo "Eingabe: \c" <nowiki># kein Zeilenvorschub </nowiki>
     echo "Eingabe: \c"   # kein Zeilenvorschub  
     read ANTW  
     read ANTW  
     case $ANTW in  
     case $ANTW in  
Zeile 455: Zeile 444:
     3) ls -CF ;;  
     3) ls -CF ;;  
     4) elm ;;  
     4) elm ;;  
    <nowiki>*) echo "Falsche Eingabe!" ;; </nowiki>
      *) echo "Falsche Eingabe!" ;;  
     esac  
     esac  
  done</div>
  done


== for-Anweisung ==
== for-Anweisung ==
Diese Schleifenanweisung hat zwei Ausprägungen, mit einer Liste der zu bearbeitenden Elemente oder mit den Kommandozeilenparametern.  
Diese Schleifenanweisung hat zwei Ausprägungen, mit einer Liste der zu bearbeitenden Elemente oder mit den Kommandozeilenparametern.  


Zeile 473: Zeile 461:
Die Syntax der for-Schleife lautet wie folgt:  
Die Syntax der for-Schleife lautet wie folgt:  


<div style="margin-left:0cm;margin-right:0cm;">for x [ in Liste ]  
for x [ in Liste ]  
  do
  do
   
   
  Befehle
  Befehle
   
   
  done</div>
  done


Die Befehle werden ausgeführt, wobei der Variablen x nacheinander die Werte aus der Liste zugewiesen werden.  
Die Befehle werden ausgeführt, wobei der Variablen x nacheinander die Werte aus der Liste zugewiesen werden.  
Zeile 487: Zeile 475:


=== for-Schleife mit Liste ===
=== for-Schleife mit Liste ===
 
for selector in liste  
<div style="margin-left:0cm;margin-right:0cm;">for selector in liste  
   do  
   do  
   Kommandofolge  
   Kommandofolge  
  done </div>
  done  


Die Selektor-Variable wird nacheinander durch die Elemente der Liste ersetzt und die Schleife mit der Selektor-Variablen ausgeführt.  
Die Selektor-Variable wird nacheinander durch die Elemente der Liste ersetzt und die Schleife mit der Selektor-Variablen ausgeführt.  
Zeile 497: Zeile 484:
'''Beispiele'''
'''Beispiele'''


<div style="margin-left:0cm;margin-right:0cm;">for X in hans heinz karl luise do echo $X done </div>
for X in hans heinz karl luise do echo $X done  


Das Programm hat folgende Ausgabe:  
Das Programm hat folgende Ausgabe:  


<div style="margin-left:0cm;margin-right:0cm;">hans
hans
  heinz
  heinz
  karl
  karl
  luise</div>
  luise
<div style="margin-left:0cm;margin-right:0cm;">for FILE in *.txt # drucke alle Textdateien
for FILE in *.txt # drucke alle Textdateien
   do # im aktuellen Verzeichnis
   do # im aktuellen Verzeichnis
   lpr $FILE
   lpr $FILE
Zeile 512: Zeile 499:
   do
   do
   echo $XX
   echo $XX
  done</div>
  done
<div style="margin-left:0cm;margin-right:0cm;"><nowiki># Durchsuche Kapitel zur Erstellung einer Wortliste (wie fgrep -f):</nowiki>
# Durchsuche Kapitel zur Erstellung einer Wortliste (wie fgrep -f):
   
   
  for item in $(cat program_list) # cat: Datei ausgeben
  for item in $(cat program_list) # cat: Datei ausgeben
Zeile 520: Zeile 507:
     echo "Referenzen zum Programm $item ..."
     echo "Referenzen zum Programm $item ..."
     grep -c "$item.[co]" chap* # grep: nach Muster suchen
     grep -c "$item.[co]" chap* # grep: nach Muster suchen
  done</div>
  done


=== for-Schleife mit Parametern ===
=== for-Schleife mit Parametern ===
 
for selector
<div style="margin-left:0cm;margin-right:0cm;">for selector
   do
   do
   Kommandofolge
   Kommandofolge
  done</div>
  done


Die Selektor-Variable wird nacheinander durch die Parameter $1 bis $n ersetzt und mit diesen Werten die Schleife durchlaufen. Es gibt also $# Schleifendurchläufe. Beispiel:  
Die Selektor-Variable wird nacheinander durch die Parameter $1 bis $n ersetzt und mit diesen Werten die Schleife durchlaufen. Es gibt also $# Schleifendurchläufe. Beispiel:  
Zeile 533: Zeile 519:
Die Prozedur 'makebak' erzeugt für die in der Parameterliste angegebenen Dateien eine .bak-Datei.  
Die Prozedur 'makebak' erzeugt für die in der Parameterliste angegebenen Dateien eine .bak-Datei.  


<div style="margin-left:0cm;margin-right:0cm;">for FF
for FF
   do
   do
   cp $FF ${FF}.bak
   cp $FF ${FF}.bak
  done</div>
  done
<div style="margin-left:0cm;margin-right:0cm;"><nowiki>#!/bin/sh </nowiki>   
#!/bin/sh    
<nowiki># Seitenweises Formatieren der Dateien, die auf der </nowiki>
  # Seitenweises Formatieren der Dateien, die auf der  
<nowiki># Befehlszeile angegeben wurden, und speichern des </nowiki>
  # Befehlszeile angegeben wurden, und speichern des  
<nowiki># jeweiligen Ergebnisses:</nowiki>
  # jeweiligen Ergebnisses:
   
   
  for file do
  for file do
     pr $file > $file.tmp # pr: Formatiert Textdateien
     pr $file > $file.tmp # pr: Formatiert Textdateien
  done</div>
  done
<div style="margin-left:0cm;margin-right:0cm;"><nowiki># Ermittle einen Ein-Wort-Titel aus jeder Datei und </nowiki>
# Ermittle einen Ein-Wort-Titel aus jeder Datei und  
<nowiki># verwende ihn als neuen Dateinamen:</nowiki>
  # verwende ihn als neuen Dateinamen:
   
   
  for file do
  for file do
     name=`sed -n 's/NAME: //p' $file`
     name=`sed -n 's/NAME: //p' $file`
    <nowiki># sed: Skriptsprache zur Textformatierung</nowiki>
      # sed: Skriptsprache zur Textformatierung
     mv $file $name  
     mv $file $name  
    <nowiki># mv: Datei verschieben bzw. umbenennen</nowiki>
      # mv: Datei verschieben bzw. umbenennen
  done</div>
  done


== while ==
== while ==
Die while-Schleife ist wieder ein Konstrukt, das einem aus vielen anderen Sprachen bekannt ist:  
Die while-Schleife ist wieder ein Konstrukt, das einem aus vielen anderen Sprachen bekannt ist:  


Die kopfgesteuerte Schleife. Die Syntax der while-Schleife lautet wie folgt:  
Die kopfgesteuerte Schleife. Die Syntax der while-Schleife lautet wie folgt:  


<div style="margin-left:0cm;margin-right:0cm;">while Bedingung
while Bedingung
  do
  do
   
   
  Befehle
  Befehle
  done</div>
  done


Die Befehle werden so lange ausgeführt, wie die Bedingung erfüllt ist.  
Die Befehle werden so lange ausgeführt, wie die Bedingung erfüllt ist.  
Zeile 575: Zeile 560:
'''Beispiele'''
'''Beispiele'''


<div style="margin-left:0cm;margin-right:0cm;"><nowiki>#!/bin/sh</nowiki>
#!/bin/sh
<nowiki># Zeilenweise Ausgabe aller Aufrufparameter:</nowiki>
  # Zeilenweise Ausgabe aller Aufrufparameter:
   
   
  while [ -n "$1"]; do
  while [ -n "$1"]; do
   
   
   echo $1  
   echo $1  
   shift <nowiki># mit shift werden die Parameter nach </nowiki>
   shift   # mit shift werden die Parameter nach  
  <nowiki># Links geshiftet (aus $2 wird $1) </nowiki>
    # Links geshiftet (aus $2 wird $1)  
  done  </div>
  done   


'''Zählschleife'''
'''Zählschleife'''
Zeile 591: Zeile 576:
Da das mit der for-Schleife der Shell nicht geht, ersetzt man die Funktion durch geschickte Anwendung der while-Schleife:  
Da das mit der for-Schleife der Shell nicht geht, ersetzt man die Funktion durch geschickte Anwendung der while-Schleife:  


<div style="margin-left:0cm;margin-right:0cm;"><nowiki>#!/bin/sh</nowiki>
#!/bin/sh
<nowiki># Ausgabe der Zahlen von 1 bis 100:</nowiki>
  # Ausgabe der Zahlen von 1 bis 100:
  i=1
  i=1
  while [ $i -le 100 ]
  while [ $i -le 100 ]
Zeile 598: Zeile 583:
     echo $i
     echo $i
     i=`expr $i + 1`
     i=`expr $i + 1`
  done</div>
  done


'''Weitere Beispiele'''
'''Weitere Beispiele'''


<div style="margin-left:0cm;margin-right:0cm;"><nowiki>#!/bin/sh</nowiki>
#!/bin/sh
   
   
  while who | grep "^root "
  while who | grep "^root "
Zeile 609: Zeile 594:
  done
  done
   
   
  echo Die Katze ist aus dem Haus, Zeit, dass die Mäuse tanzen!</div>
  echo Die Katze ist aus dem Haus, Zeit, dass die Mäuse tanzen!


'''Ergebniswert eines Kommandos'''
'''Ergebniswert eines Kommandos'''
Zeile 615: Zeile 600:
Als Bedingung kann nicht nur eine "klassische" Bedingung (<tt>test</tt> oder <tt>[ ]</tt>) sondern auch der Ergebniswert eines Kommandos oder einer Kommandofolge verwendet werden.  
Als Bedingung kann nicht nur eine "klassische" Bedingung (<tt>test</tt> oder <tt>[ ]</tt>) sondern auch der Ergebniswert eines Kommandos oder einer Kommandofolge verwendet werden.  


<div style="margin-left:0cm;margin-right:0cm;">while Bedingung
while Bedingung
   do
   do
   Kommandofolge
   Kommandofolge
   done</div>
   done


Solange der Bedingungsausdruck den Wert 'true' liefert, wird die Schleife ausgeführt.  
Solange der Bedingungsausdruck den Wert 'true' liefert, wird die Schleife ausgeführt.  
Zeile 624: Zeile 609:
'''Warten auf eine Datei (z. B. vom Hintergrundprozess) '''
'''Warten auf eine Datei (z. B. vom Hintergrundprozess) '''


<div style="margin-left:0cm;margin-right:0cm;">while [ ! -f foo ]
while [ ! -f foo ]
   do
   do
   sleep 10 # Wichtig damit die Prozesslast nicht zu hoch wird
   sleep 10 # Wichtig damit die Prozesslast nicht zu hoch wird
  done</div>
  done


'''Pausenfüller für das Terminal Abbruch mit DEL-Taste '''
'''Pausenfüller für das Terminal Abbruch mit DEL-Taste '''


<div style="margin-left:0cm;margin-right:0cm;">while :
while :
   do
   do
   tput clear # BS löschen
   tput clear # BS löschen
Zeile 637: Zeile 622:
   banner $(date '+ %T ') # Uhrzeit groß
   banner $(date '+ %T ') # Uhrzeit groß
   sleep 10 # 10s Pause
   sleep 10 # 10s Pause
  done</div>
  done


'''Umbenennen von Dateien durch Anhängen eines Suffix '''
'''Umbenennen von Dateien durch Anhängen eines Suffix '''


<div style="margin-left:0cm;margin-right:0cm;"><nowiki># Aufruf change suffix datei(en)</nowiki>
# Aufruf change suffix datei(en)
  if [ $# -lt 2 ] ; then
  if [ $# -lt 2 ] ; then
   echo "Usage: `basename $0` suffix file(s)"
   echo "Usage: `basename $0` suffix file(s)"
Zeile 652: Zeile 637:
   shift
   shift
   done
   done
  fi</div>
  fi


'''Umbenennen von Dateien durch Anhängen eines Suffix Variante 2 mit for '''
'''Umbenennen von Dateien durch Anhängen eines Suffix Variante 2 mit for '''


<div style="margin-left:0cm;margin-right:0cm;"><nowiki># Aufruf change suffix datei(en)</nowiki>
# Aufruf change suffix datei(en)
  if [ $# -lt 2 ] ; then
  if [ $# -lt 2 ] ; then
   echo "Usage: `basename $0` suffix file(s)"
   echo "Usage: `basename $0` suffix file(s)"
Zeile 667: Zeile 652:
   shift
   shift
   done
   done
  fi</div>
  fi


== until-Anweisung ==
== until-Anweisung ==
Diese Anweisung ist identisch zu einer <tt>while</tt>-Schleife mit negierter Bedingung.  
Diese Anweisung ist identisch zu einer <tt>while</tt>-Schleife mit negierter Bedingung.  


Als Bedingung kann nicht nur eine "klassische" Bedingung (<tt>test</tt> oder <tt>[ ]</tt>) sondern auch der Ergebniswert eines Kommandos oder einer Kommandofolge verwendet werden.  
Als Bedingung kann nicht nur eine "klassische" Bedingung (<tt>test</tt> oder <tt>[ ]</tt>) sondern auch der Ergebniswert eines Kommandos oder einer Kommandofolge verwendet werden.  


<div style="margin-left:0cm;margin-right:0cm;">until Bedingung
until Bedingung
   do
   do
   Kommandofolge
   Kommandofolge
  done</div>
  done


Die Schleife wird solange abgearbeitet, bis Bedingungsausdruck einen Wert ungleich Null liefert.  
Die Schleife wird solange abgearbeitet, bis Bedingungsausdruck einen Wert ungleich Null liefert.  
Zeile 684: Zeile 668:
<u>Beispiel</u>
<u>Beispiel</u>


<div style="margin-left:0cm;margin-right:0cm;"><nowiki># warten auf Datei foo</nowiki>
# warten auf Datei foo
  until [ -f foo ]
  until [ -f foo ]
   do
   do
   sleep 10
   sleep 10
  done</div>
  done


<u>Warten auf einen Benutzer</u>
<u>Warten auf einen Benutzer</u>


<div style="margin-left:0cm;margin-right:0cm;"><nowiki># warten, bis sich der Benutzer hans eingeloggt hat</nowiki>
# warten, bis sich der Benutzer hans eingeloggt hat
  TT=`who | grep -c "hans"`
  TT=`who | grep -c "hans"`
  until [ $TT -gt 0 ]
  until [ $TT -gt 0 ]
Zeile 698: Zeile 682:
   sleep 10
   sleep 10
   TT=`who | grep -c "hans"`
   TT=`who | grep -c "hans"`
  done</div>
  done
<div style="margin-left:0cm;margin-right:0cm;"><nowiki># warten, bis sich der Benutzer hans eingeloggt hat</nowiki>
# warten, bis sich der Benutzer hans eingeloggt hat
<nowiki># Variante 2 – kuerzer</nowiki>
  # Variante 2 – kuerzer
  until [ `who | grep -c "hans"` -gt 0 ]
  until [ `who | grep -c "hans"` -gt 0 ]
   do
   do
   sleep 10
   sleep 10
  done</div>
  done


Die Befehle werden ausgeführt, bis die Bedingung erfüllt ist. Die Bedingung wird dabei üblicherweise, genau wie bei der if-Anweisung, mit dem Befehl test formuliert.  
Die Befehle werden ausgeführt, bis die Bedingung erfüllt ist. Die Bedingung wird dabei üblicherweise, genau wie bei der if-Anweisung, mit dem Befehl test formuliert.  
Zeile 714: Zeile 698:
Hier wird die Bedingung nicht per test, sondern mit dem Rückgabewert des Programms grep formuliert.  
Hier wird die Bedingung nicht per test, sondern mit dem Rückgabewert des Programms grep formuliert.  


<div style="margin-left:0cm;margin-right:0cm;"><nowiki>#!/bin/sh</nowiki>
#!/bin/sh
<nowiki># Warten, bis sich der Administrator einloggt:</nowiki>
  # Warten, bis sich der Administrator einloggt:
   
   
  until who | grep "root"; do
  until who | grep "root"; do
<nowiki># who: Liste der Benutzer</nowiki>
  # who: Liste der Benutzer
<nowiki># grep: Suchen nach Muster</nowiki>
  # grep: Suchen nach Muster
     sleep 30 # sleep: warten
     sleep 30 # sleep: warten
  done
  done
  echo "Der Meister ist anwesend"</div>
  echo "Der Meister ist anwesend"

Version vom 3. Juli 2021, 13:47 Uhr

Kontrollstrukturen

Bei der Shell-Programmierung verfügt man über ähnliche Konstrukte wie bei anderen Programmiersprachen, um den Ablauf des Programms zu steuern. Dazu gehören bedingte Verzweigungen, Schleifen und Fallunterscheidungen.

Bedingungen testen

Das wichtigste Kommando ist 'test', mit dem man mannigfache Bedingungen testen kann.

test Argument 

Dieses Kommando prüft eine Bedingung und liefert 'true' (0), falls die Bedingung erfüllt ist und 'false' (1), falls die Bedingung nicht erfüllt ist. Der Fehlerwert 2 wird zurückgegeben, wenn das Argument syntaktisch falsch ist (meist durch Ersetzung hervorgerufen).

Es lassen sich Dateien, Zeichenketten und Integer-Zahlen (16 Bit, bei Linux 32 Bit) überprüfen. Das Argument von Test besteht aus einer Testoption und einem Operanden, der ein Dateiname oder eine Shell-Variable (Inhalt: String oder Zahl) sein kann.

In bestimmten Fällen können auf der rechten Seite eines Vergleichs auch Strings oder Zahlen stehen - bei der Ersetzung von leeren Variablen kann es aber zu Syntaxfehlern kommen. Weiterhin lassen sich mehrere Argumente logisch verknüpfen (UND, ODER, NICHT). Beispiel:

test -w /etc/passwd 

mit der Kommandoverkettung lassen sich so schon logische Entscheidungen treffen, z. B.:

test -w /etc/passwd && echo "Du bist ROOT" 

Normalerweise kann statt 'test' das Argument auch in eckigen Klammern gesetzt werden. Die Klammern müssen von Leerzeichen umschlossen werden:

[ -w /etc/passwd ] 

Die folgenden Operationen können bei 'test' bzw. [ ... ] verwendet werden.


Dateitests:
-b Datei Die Datei existiert und ist ein blockorientiertes Gerät
-c Datei Die Datei existiert und ist ein zeichenorientiertes Gerät
-d Datei Die Datei existiert und ist ein Verzeichnis
-e Datei Datei existiert
-f Datei Die Datei existiert und ist eine reguläre Datei
-g Datei Die Datei existiert und das Gruppen-ID-Bit ist gesetzt
-h Datei Die Datei existiert und ist ein symbolischer Link
-k Datei Die Datei existiert und das Sticky-Bit ist gesetzt
-p Datei Die Datei existiert und ist eine Named Pipe
-r Datei Die Datei existiert und ist lesbar
-s Datei Die Datei existiert und ist nicht leer
-t [n] DATEI-Descriptor FD (Standard: Standardausgabe) ist auf Tty offen
-u Datei Die Datei existiert und das Setuid-Bit ist gesetzt
-w Datei Die Datei existiert und ist beschreibbar
-x Datei Die Datei existiert und ist ausführbar
Datei1 -nt Datei2 Datei1 ist neuer als Datei2
Datei1 -ot Datei2 Datei1 ist älter als Datei2
Datei1 -ef Datei2 Beide Dateien belegen dieselbe Inode auf demselben Gerät

Beispiel

if [ -d RCS ] Wenn ein Verzeichnis RCS existiert. . .


Bedingungen für Zeichenfolgen:
-n s1 Die Länge der Zeichenfolge s1 ist ungleich Null
-z s1 Die Länge der Zeichenfolge s1 ist gleich Null
s1 = s2 Die Zeichenfolgen s1 und s2 sind identisch
s1 != s2 Die Zeichenfolgen s1 und s2 sind nicht identisch
Zeichenfolge Die Zeichenfolge ist nicht Null

Beispiel

if [ "$Antwort" != "j" ]     Wenn die $Antwort nicht "j" ist. . .
Ganzzahlvergleiche:
n1 -eq n2 n1 ist gleich n2
n1 -ge n2 n1 ist größer oder gleich n2
n1 -gt n2 n1 ist größer als n2
n1 -le n2 n1 ist kleiner oder gleich n2
n1 -lt n2 n1 ist kleiner n2
n1 -ne n2 n1 ist ungleich n2

Beispiele

while test $# -gt 0     Solange Argumente vorliegen. . .

while [ -n "$1" ]     Solange das erste Argument nicht leer ist. . .

if [ $count -lt 10 ]     Wenn $count kleiner 10. . .
Kombinierte Formen:
(Bedingung) Wahr, wenn die Bedingung zutrifft (wird für die Gruppierung verwendet). Den Klammern muss ein \ vorangestellt werden.
! Bedingung i Wahr, wenn die Bedingung nicht zutrifft (NOT).
Bedingung1 -a Bedingung2 Wahr, wenn beide Bedingungen zutreffen (AND).
Bedingung1 -o Bedingung2 Wahr, wenn eine der beiden Bedingungen zutrifft (OR).

Beispiel

if [ ! -r "$1" -o ! -f "$1" ]    Wenn das erste Argument keine lesbare oder reguläre Datei ist.

Bedingte Anweisung (if - then - else)

Wichtig: Als Bedingung kann nicht nur der test-Befehl, sondern eine beliebige Folge von Kommados verwendet werden.

Jedes Kommando liefert einen Errorcode zurück, der bei erfolgreicher Ausführung gleich Null (true) und bei einem Fehler oder Abbruch ungleich Null (false) ist.

Zum Testen einer Bedingung dient die if-Anweisung.

Jede Anweisung muss entweder in einer eigenen Zeile stehen oder durch einen Strichpunkt von den anderen Anweisungen getrennt werden.

Trotzdem verhät sich eine bedingte Anweisung - oder die Schleifenkonstrukte, die weiter unten behandelt werden - wie eine einzige Anweisung.

Somit ergibt sich eine starke Ähnlichkeit mit der Blockstruktur von C oder Pascal.

Man kann dies ausprobieren, indem man eine if- oder while-Anweisung interaktiv eingibt. Solange nicht 'fi' bzw. 'done' eingetippt wurde, erhält man den PS2-Prompt ('>').

if

Die if-Anweisung in der Shell-Programmierung macht das gleiche wie in allen anderen Programmiersprachen, sie testet eine Bedingung auf Wahrheit und macht davon den weiteren Ablauf des Programms abhängig.

Die Syntax der if-Anweisung lautet wie folgt:

if Bedingung1
    then Befehle1
[ elif Bedingung2
    then Befehle2 ]
...
[ else Befehle3 ]
fi

Wenn die Bedingung1 erfüllt ist, werden die Befehle1 ausgeführt; andernfalls, wenn die Bedingung2 erfüllt ist, werden die Befehle2 ausgeführt. Trifft keine Bedingung zu, sollen die Befehle3 ausgeführt werden.

Bedingungen werden normalerweise mit dem Befehl test formuliert. Es kann aber auch der Rückgabewert jedes anderen Kommandos ausgewertet werden. Für Bedingungen, die auf jeden Fall zutreffen sollen steht der Null-Befehl (:) zur Verfügung.

Beispiele

Man achte auf die Positionierung der Semikoli.

#!/bin/sh
 # Füge eine 0 vor Zahlen kleiner 10 ein:
counter=0
if [ $counter -lt 10 ]; then

number=0$counter; else number=$counter; fi
#!/bin/bash
 # Erstelle ein Verzeichnis, wenn es noch nicht existiert:
dir=daten
if [ ! -e $dir ]; then
mkdir $dir; fi # mkdir: Verzeichnis erstellen

einseitiges if

if kommandoliste 
then 
      kommandos 
fi 

zweiseitiges if

if kommandoliste 
then 
      kommandos 
else 
      kommandos 
fi 

Mehrstufiges if

if kommandoliste1 
then 
      kommandos
elif kommandoliste2 
  then 
        kommandos 
elif ... 
          ... 
fi 

Beispiele

Es soll eine Meldung ausgegeben werden, falls mehr als 5 Benutzer eingeloggt sind:

USERS=`who | wc -l`   # Zeilen der who-Ausgabe zählen
if test $USERS -gt 5 
then 
  echo "Mehr als 5 Benutzer am Geraet" 
fi 

Das geht natürlich auch kürzer und ohne Backtics:

if [ $(who | wc -l) -gt 5 ] ; then 
  echo "Mehr als 5 Benutzer am Geraet" 
fi 

Man sollte bei der Entwicklung von Skripts aber ruhig mit der Langfassung beginnen und sich erst der Kurzfassung zuwenden, wenn man mehr Übung hat und die Langfassungen auf Anhieb funktionieren.

Ein weiteres Beispiel zeigt eine Fehlerprüfung:

if test $# -eq 0 
then 
  echo "usage: sortiere filename" >&2 
else 
  sort +1 -2 $1 | lp 
fi 

Das nächste Beispiel zeigt eine mehr oder weniger intelligente Anzeige für Dateien und Verzeichnisse. 'show' zeigt bei Dateien den Inhalt mit 'less' an und Verzeichnisse werden mit 'ls' präsentiert.

Fehlt der Parameter, wird interaktiv nachgefragt:

if [ $# -eq 0 ]                           # falls keine Angabe 
then                                      # interaktiv erfragen 
   echo -n "Bitte Namen eingeben: "
   read DATEI 
else  
   DATEI=$1 
fi
if  [ -f $DATEI ]                          # wenn normale Datei 
then                                      # dann ausgeben 
   less $DATEI  
elif [ -d $DATEI ]                        # wenn aber Verzeichnis 
  then                                    # dann Dateien zeigen 
     ls -CF $DATEI 
   else                                   # sonst Fehlermeldung 
     echo "cannot show $DATEI"  
fi

Das nächste Beispiel hängt eine Datei an eine andere Datei an; vorher erfolgt eine Prüfung der Zugriffsberechtigungen:

append Datei1 Datei2

if [ -r $1 -a -w $2 ] 
then 
   cat $1 >> $2 
else 
    echo "cannot append" 
fi 

Beim Vergleich von Zeichenketten sollten möglichst die Anführungszeichen (" ... ") verwendet werden, da sonst bei der Ersetzung durch die Shell unvollständige Test-Kommandos entstehen können.

Dazu ein Beispiel:

if [ ! -n $1 ] ; then 
   echo "Kein Parameter" 
fi 

Ist $1 wirklich nicht angegeben, wird das Kommando reduziert zu:

if [ ! -n ] ; then .... 

Es ist also unvollständig und es erfolgt eine Fehlermeldung. Dagegen liefert

if [ ! -n "$1" ] ; then 
    echo "Kein Parameter" 
fi 

bei fehlendem Parameter den korrekten Befehl

if [ ! -n "" ] 

Bei fehlenden Anführungszeichen werden auch führende Leerzeichen der Variablenwerte oder Parameter eliminiert.

Noch ein Beispiel

Es kommt ab und zu vor, dass eine Userid wechselt oder dass die Gruppenzugehörigkeit von Dateien geändert werden muss. In solchen fällen helfen die beiden folgenden Skripts:

#!/bin/sh
 # Change user-id
 #
if [ $# -ne 2 ] ; then
  echo "usage `basename $0` <old id> <new id>"
  exit
fi
find ~ -user $1 -exec chown $2 {} ";"
#!/bin/sh
 # Change group-id
 #
if [ $# -ne 2 ] ; then
  echo "usage `basename $0` <old id> <new id>"
  exit
fi
find / -group $1 -exec chgrp $2 {} ";"

case

Auch die case-Anweisung ist vergleichbar in vielen anderen Sprachen vorhanden.

Sie dient, ähnlich wie die if-Anweisung, zur Fallunterscheidung. Allerdings wird hier nicht nur zwischen zwei Fällen unterschieden (Entweder / Oder), sondern es sind mehrere Fälle möglich.

Man kann die case-Anweisung auch durch eine geschachtelte if-Anweisung völlig umgehen, allerdings ist sie ein elegantes Mittel um den Code lesbar zu halten.

Die Syntax der case-Anweisung lautet wie folgt:

case Wert in
    Muster1) Befehle1;;
    Muster2) Befehle2;;
...

esac

Wenn der Wert mit dem Muster1 übereinstimmt, wird die entsprechende Befehlsgruppe (Befehle1) ausgeführt, bei Übereinstimmung mit Muster2 werden die Kommandos der zweiten Befehlsgruppe (Befehle2) ausgeführt, usw.

Der letzte Befehl in jeder Gruppe muss mit ;; gekennzeichnet werden.

Das bedeutet für die Shell soviel wie springe zum nächsten esac, so dass die anderen Bedingungen nicht mehr überprüft werden.

In den Mustern sind die gleichen Meta-Zeichen erlaubt wie bei der Auswahl von Dateinamen.

Wenn in einer Zeile mehrere Muster angegeben werden sollen, müssen sie durch ein Pipezeichen (|, logisches ODER) getrennt werden.

Beispiele

#!/bin/sh
 # Mit dem ersten Argument in der Befehlszeile 
 # wird die entsprechende Aktion festgelegt:

case $1 in # nimmt das erste Argument
     Ja|Nein) response=1;;
            *) echo "Unbekannte Option"; exit 1;;
esac


#!/bin/sh
 # Lies die Zeilen von der Standardeingabe, bis eine
 # Zeile mit einem einzelnen Punkt eingegeben wird:
while : # Null-Befehl
do
    echo -e "Zum Beenden . eingeben ==> \c"
    read line # read: Zeile von StdIn einlesen
    case "$line" in
         .) echo "Ausgefuehrt"
            break;;
          *) echo "$line" >>./message ;;
    esac
done

case-Anweisung

Diese Anweisung erlaubt eine Mehrfachauswahl. Sie wird auch gerne deshalb verwendet, weil sie Muster mit Jokerzeichen und mehrere Muster für eine Auswahl erlauben

case selector in 
     Muster-1) Kommandofolge 1 ;; 
     Muster-2) Kommandofolge 2 ;; 
             .... 

     Muster-n) Kommandofolge n ;; 
esac 

Die Variable selector (String) wird der Reihe nach mit den Mustern "Muster-1" bis "Muster-n" verglichen. Bei Gleichheit wird die nachfolgende Kommandofolge ausgeführt und dann nach der case-Anweisung (also hinter dem esac) fortgefahren. * In den Mustern sind Metazeichen (*, ?, []) erlaubt, im Selektor dagegen nicht.

  • Das Muster * deckt sich mit jedem Selektor --> default-Ausgang. muss als letztes Muster in der case-Konstruktion stehen.
  • Vor der Klammer können mehrere Muster, getrennt durch | stehen. Das Zeichen | bildet eine Oder-Bedingung:
case selector in 
     Muster1)              Kommandofolge1 ;; 
     Muster2 | Muster3)    Kommandofolge2 ;; 
      *)                    Kommandofolge3 ;; 
esacBeispiel 1: Automatische Bearbeitung von Quell- und Objekt-Dateien. Der Aufruf erfolgt mit 'compile Datei'. 
case $1 in 
    *.s) as $1 ;;                        # Assembler aufrufen 
    *.c) cc -c $1 ;;                     # C-Compiler aufrufen 
    *.o) cc $1 -o prog ;;                # C-Compiler als Linker 
      *) echo "invalid parameter: $1";; 
esac

Beispiel 2: Menü mit interaktiver Eingabe

while :   # Endlosschleife (s. später) 
do 
tput clear   # Schirm löschen und Menütext ausgeben 
   echo " +---------------------------------+"  
   echo " | 0 --> Ende                      |" 
   echo " | 1 --> Datum und Uhrzeit         |" 
   echo " | 2 --> aktuelles Verzeichnis     |" 
   echo " | 3 --> Inhaltsverzeichnis        |" 
   echo " | 4 --> Mail                      |" 
   echo "+----------------------------------+" 
   echo "Eingabe: \c"   # kein Zeilenvorschub 
   read ANTW 
   case $ANTW in 
    0) kill -9 0 ;; # und tschuess 
    1) date ;;  
    2) pwd ;; 
    3) ls -CF ;; 
    4) elm ;; 
     *) echo "Falsche Eingabe!" ;; 
   esac 
done

for-Anweisung

Diese Schleifenanweisung hat zwei Ausprägungen, mit einer Liste der zu bearbeitenden Elemente oder mit den Kommandozeilenparametern.

Dieses Konstrukt ähnelt nur auf den ersten Blick seinen Pendants aus anderen Programmiersprachen.

In anderen Sprachen wird die for-Schleife meistens dazu benutzt, eine Zählvariable über einen bestimmten Wertebereich iterieren zu lassen (for i = 1 to 100...next).

In der Shell dagegen wird die Laufvariable nicht mit aufeinander folgenden Zahlen belegt, sondern mit einzelnen Werten aus einer anzugebenden Liste.

Wenn man eine Laufvariable benötigt, muss man dazu die while-Schleife einsetzen.

Die Syntax der for-Schleife lautet wie folgt:

for x [ in Liste ] 
do

Befehle

done

Die Befehle werden ausgeführt, wobei der Variablen x nacheinander die Werte aus der Liste zugewiesen werden.

Wie man sieht ist die Angabe der Liste optional, wenn sie nicht angegeben wird, nimmt x der Reihe nach alle Werte aus $@ (in dieser vordefinierten Variablen liegen die Aufrufparameter) an.

Wenn die Ausführung eines Schleifendurchlaufs bzw. der ganzen Schleife abgebrochen werden soll, müssen die Kommandos continue bzw. break benutzt werden.

for-Schleife mit Liste

for selector in liste 
  do 
  Kommandofolge 
done 

Die Selektor-Variable wird nacheinander durch die Elemente der Liste ersetzt und die Schleife mit der Selektor-Variablen ausgeführt.

Beispiele

for X in hans heinz karl luise do echo $X done 

Das Programm hat folgende Ausgabe:

hans
heinz
karl
luise
for FILE in *.txt # drucke alle Textdateien
 do # im aktuellen Verzeichnis
 lpr $FILE
done
for XX in $VAR # geht auch mit
 do
 echo $XX
done
# Durchsuche Kapitel zur Erstellung einer Wortliste (wie fgrep -f):

for item in $(cat program_list) # cat: Datei ausgeben
do
    echo "Pruefung der Kapitel auf"
    echo "Referenzen zum Programm $item ..."
    grep -c "$item.[co]" chap* # grep: nach Muster suchen
done

for-Schleife mit Parametern

for selector
 do
 Kommandofolge
done

Die Selektor-Variable wird nacheinander durch die Parameter $1 bis $n ersetzt und mit diesen Werten die Schleife durchlaufen. Es gibt also $# Schleifendurchläufe. Beispiel:

Die Prozedur 'makebak' erzeugt für die in der Parameterliste angegebenen Dateien eine .bak-Datei.

for FF
 do
 cp $FF ${FF}.bak
done
#!/bin/sh     
 # Seitenweises Formatieren der Dateien, die auf der 
 # Befehlszeile angegeben wurden, und speichern des 
 # jeweiligen Ergebnisses:

for file do
    pr $file > $file.tmp # pr: Formatiert Textdateien
done
# Ermittle einen Ein-Wort-Titel aus jeder Datei und 
 # verwende ihn als neuen Dateinamen:

for file do
    name=`sed -n 's/NAME: //p' $file`
     # sed: Skriptsprache zur Textformatierung
    mv $file $name 
     # mv: Datei verschieben bzw. umbenennen
done

while

Die while-Schleife ist wieder ein Konstrukt, das einem aus vielen anderen Sprachen bekannt ist:

Die kopfgesteuerte Schleife. Die Syntax der while-Schleife lautet wie folgt:

while Bedingung
do

Befehle
done

Die Befehle werden so lange ausgeführt, wie die Bedingung erfüllt ist.

Dabei wird die Bedingung vor der Ausführung der Befehle überprüft. Die Bedingung wird dabei üblicherweise, genau wie bei der if-Anweisung, mit dem Befehl test formuliert.

Wenn die Ausführung eines Schleifendurchlaufs bzw. der ganzen Schleife abgebrochen werden soll, müssen die Kommandos continue bzw. break benutzt werden.

Beispiele

#!/bin/sh
 # Zeilenweise Ausgabe aller Aufrufparameter:

while [ -n "$1"]; do

 echo $1 
 shift   # mit shift werden die Parameter nach 
   # Links geshiftet (aus $2 wird $1) 
done   

Zählschleife

In anderen Sprachen kann man mit der for-Schleife eine Zählvariable über einen bestimmten Wertebereich iterieren lassen (for i = 1 to 100...next).

Da das mit der for-Schleife der Shell nicht geht, ersetzt man die Funktion durch geschickte Anwendung der while-Schleife:

#!/bin/sh
 # Ausgabe der Zahlen von 1 bis 100:
i=1
while [ $i -le 100 ]
do
    echo $i
    i=`expr $i + 1`
done

Weitere Beispiele

#!/bin/sh

while who | grep "^root "
do sleep 30

done

echo Die Katze ist aus dem Haus, Zeit, dass die Mäuse tanzen!

Ergebniswert eines Kommandos

Als Bedingung kann nicht nur eine "klassische" Bedingung (test oder [ ]) sondern auch der Ergebniswert eines Kommandos oder einer Kommandofolge verwendet werden.

while Bedingung
 do
 Kommandofolge
 done

Solange der Bedingungsausdruck den Wert 'true' liefert, wird die Schleife ausgeführt.

Warten auf eine Datei (z. B. vom Hintergrundprozess)

while [ ! -f foo ]
 do
 sleep 10 # Wichtig damit die Prozesslast nicht zu hoch wird
done

Pausenfüller für das Terminal Abbruch mit DEL-Taste

while :
 do
 tput clear # BS löschen
 echo -e "\n\n\n\n\n" # 5 Leerzeilen
 banner $(date '+ %T ') # Uhrzeit groß
 sleep 10 # 10s Pause
done

Umbenennen von Dateien durch Anhängen eines Suffix

# Aufruf change suffix datei(en)
if [ $# -lt 2 ] ; then
 echo "Usage: `basename $0` suffix file(s)"
else
 SUFF=$1 # Suffix speichern
 shift
 while [ $# -ne 0 ] # solange Parameter da sind
 do
 mv $1 ${1}.$SUFF # umbenennen
 shift
 done
fi

Umbenennen von Dateien durch Anhängen eines Suffix Variante 2 mit for

# Aufruf change suffix datei(en)
if [ $# -lt 2 ] ; then
 echo "Usage: `basename $0` suffix file(s)"
else
 SUFF=$1 # Suffix speichern
 shift
 for FILE
 do
 mv $FILE ${FILE}.$SUFF # umbenennen
 shift
 done
fi

until-Anweisung

Diese Anweisung ist identisch zu einer while-Schleife mit negierter Bedingung.

Als Bedingung kann nicht nur eine "klassische" Bedingung (test oder [ ]) sondern auch der Ergebniswert eines Kommandos oder einer Kommandofolge verwendet werden.

until Bedingung
 do
 Kommandofolge
done

Die Schleife wird solange abgearbeitet, bis Bedingungsausdruck einen Wert ungleich Null liefert.

Beispiel

# warten auf Datei foo
until [ -f foo ]
 do
 sleep 10
done

Warten auf einen Benutzer

# warten, bis sich der Benutzer hans eingeloggt hat
TT=`who | grep -c "hans"`
until [ $TT -gt 0 ]
 do
 sleep 10
 TT=`who | grep -c "hans"`
done
# warten, bis sich der Benutzer hans eingeloggt hat
 # Variante 2 – kuerzer
until [ `who | grep -c "hans"` -gt 0 ]
 do
 sleep 10
done

Die Befehle werden ausgeführt, bis die Bedingung erfüllt ist. Die Bedingung wird dabei üblicherweise, genau wie bei der if-Anweisung, mit dem Befehl test formuliert.

Wenn die Ausführung eines Schleifendurchlaufs bzw. der ganzen Schleife abgebrochen werden soll, müssen die Kommandos continue bzw. break benutzt werden.

Beispiel

Hier wird die Bedingung nicht per test, sondern mit dem Rückgabewert des Programms grep formuliert.

#!/bin/sh
 # Warten, bis sich der Administrator einloggt:

until who | grep "root"; do
 # who: Liste der Benutzer
 # grep: Suchen nach Muster
    sleep 30 # sleep: warten
done
echo "Der Meister ist anwesend"