Kontrollstrukturen in der Shell

Diese Seite gehört zum Shellkurs.

 

Kontrollstrukturen sind Verzweigungen im Programmfluss, also Entscheidungen der Art

  • Mache dies nur dann, wenn die Datei existiert.
  • Wenn die Datei existiert, dann mache dies, anderenfalls mache das.

Das ist nicht grundsätzlich anders als in "richtigen" Programmiersprachen. Ein wesentlicher praktischer Unterschied (der allerdings nicht immer auffällt): In der Shell werden diese Entscheidungen auf Grund des exit codes eines Programms getroffen, was anderswo die Ausnahme ist.

 

exit codes

Der exit code eines Programms ist eine ganze Zahl von 0 bis 255, die das Programm bei seiner Beendigung an das Betriebssystem zurückliefert und die vom Elternprozess abgefragt werden kann. Innerhalb eines Programms gibt es einen vergleichbaren Mechanismus (für Funktionsaufrufe). Laut Konvention steht 0 für eine erfolgreiche Beendigung des Programms, alle anderen Werte für einen Fehler. Die Shell prüft deshalb nur, ob der exit code Null ist. Nicht jede Programmbeendigung mit einem exit code ungleich Null ist inhaltlich als Fehler anzusehen. In solchen Fällen muss man sich den exit code genauser anschauen und differenziert auf die möglichen Ergebnisse reagieren. Der exit code (von Vordergrundprozessen) findet sich in der Shellvariable $?. Die Hilfsprogramme true und false machen nichts weiter, als einen exit code von Null bzw. Eins zu produzieren. Wenn man ein Shellscript per exit beendet (oder eine Shellfunktion mit return), dann kann man einen exit code übergeben.

 

$ false
$ echo $?
1
$ true
$ echo $?
0
$ bash -c 'exit 5'
$ echo $?
5

logische Verknüpfungen

Man kann einzelne Kommandos oder Gruppen von Kommandos (Pipielines und Blöcke) mit einer UND-Verknüpfung (&&) oder einer ODER-Verknüpfung (||) aneinanderreihen.

$ true && echo foo
foo
$ false && echo foo

$ true || echo foo

$ false || echo foo
foo

Wenn sich die Verzweigung auf ganze Gruppen von Kommandos beziehen soll, kann man mit { cmd; } (das Semikolon oder den Zeilenumbruch vor der schließenden Klammer nicht vergessen!) oder ( cmd ) klammern. Die erste Variante verbindet mehrere Kommandos zu einer Einheit, die zweite führt sie darüber hinaus in einer Subshell aus, was zumeist kein relevanter Unterschied ist. Wichtige Ausnahme: In dem Block werden Variablen gesetzt, die danach noch verfügbar sein sollen.

$ true && false && echo foo

$ true && false || echo foo
foo
$ false && true && echo foo

$ false && true || echo foo
foo
$ false || true && echo foo
foo
$ { true || false; } || echo foo

$ { true && false; } || { true && echo foo; }
foo

if-elif-else-Blöcke

Der Übersichtlichkeit ist es bei längeren Blöcken oder längeren Konstrukten zumeist dienlich, statt der geklammerten Listen if-Blöcke zu verwenden. Alles zwischen einem if und dem entsprechenden Semikolon (oder Zeilenumbruch) wird ausgeführt. Bei einem exit code von Null wird der Block ausgeführt.

$ if true; then
echo foo
fi
foo

 

$

 

$