Die Bash, das unbekannte Wesen
Hardcore Linux
Verkettete Befehle
Pipes sind nur zwischen mehreren, miteinander in Beziehung stehenden Befehlen sinnvoll. Aufgrund der Struktur und dem Konzept der Befehle unter Linux ist das bei sehr vielen (fast allen) Aufgabenstellungen ähnlich. Die einzelnen Shell-Befehle stellen kleine, einfache Bearbeitungsmodule dar, die nach Bedarf kombiniert und ersetzt werden können. Gerade diese Eigenschaften machen die Leistungsfähigkeit und den Reiz bei der Arbeit mit der Shell aus. Es gibt eine Reihe von Befehlen, die ausschließlich für den Einsatz in durch Pipes verbundenen Befehlsketten konzipiert sind, die sogenannten "Filter". Derartige Befehle verfügen über keine Option, mit der sie Daten direkt aus einer Datei lesen oder in eine Datei schreiben können. Die gesamte Kommunikation wird über die Standardkanäle abgewickelt. Typische Filter sind z.B. tr, uniq, colrm, … Betrachtet man die Anwendung von Befehlsketten genauer, so treten einige typische Fälle immer wieder auf:
- mehrere Befehle werden nacheinander ausgeführ
- mehrere Befehle werden parallel zueinander ausgeführ
- mehrere Befehle werden abhängig vom vorherigen Befehl ausgeführ
- identische Befehlsgruppen werden in unterschiedlichem Kontext ausgeführ
Normalerweise werden Befehle einzeln in einer Befehlszeile eingegeben und ausgeführt. Manchmal ist es aber übersichtlicher, mehrere, eng zusammenarbeitende Befehle in einer Befehlszeile einzugeben und diese dann gemeinsam ausführen zu lassen. Die Bash verwendet das Semikolon für die Abgrenzung der einzelnen Befehle (bzw. -szeilen). Ein Beispiel:
$> cd find . -print > find.tmp less find.tmp cd -
Der cd-Befehl bewirkt, ohne dass ein Argument angegeben wird, den Wechsel in das Homeverzeichnis des Anwenders. Dort erstellt find eine Liste aller Dateien, die in find.tmp gespeichert wird. less wird als Pager zur Anzeige (und zum Suchen in dieser Datei) verwendet. Abschließend wechselt cd mit dem Argument "-" zurück in das ursprüngliche Verzeichnis.
Die einfachste Lösung für das Zusammenfassen dieser Befehlszeilen wäre:
$> cd ; find . -print > find.tmp ; less find.tmp ; cd -
Die Leerzeichen vor und hinter einem Semikolon dienen nur der besseren Lesbarkeit, sie können auch entfallen. Diese einfachste Form der Befehlsverkettung hat einige Nachteile: Zunächst einmal ist der abschließende cd-Befehl gar nicht unbedingt notwendig, wenn nämlich die Ausführung dieser Befehle in einer Subshell (einer nur zu diesem Zweck implizit gestarteten Shell) erfolgt. Nach dem Ende der Bearbeitung befindet sich die aufrufende Shell immer noch im selben Verzeichnis wie vorher. Runde Klammern starten auf der Bash eine Subshell:
$> pwd /mydir (cd ; find . -print > find.tmp ; less find.tmp) pwd /mydir
Als nächstes stellt sich die Frage, was geschieht, wenn in der Bearbeitung der Befehlsfolge ein Fehler auftritt. Die Anzeige der durch find erzeugten Datei ist sinnlos, wenn diese beispielsweise aus Platzmangel auf dem Datenträger nicht vollständig erstellt werden konnte.
Die Bash kennt zwei spezielle Operatoren, mit denen Befehle nur in Abhängigkeit vom Ergebnis des vorher ausgeführten gestartet werden. Durch ein doppeltes Ampersand-Zeichen "&&" wird zunächst der links davon stehende Befehl ausgeführt und nur dann, wenn dieser fehlerfrei abgearbeitet werden konnte, der rechts davon stehende:
$> find . -print > find.tmp && less find.tmp
Die Bash wertet zu diesem Zweck den sogenannten "Return Code" (Rückgabewert) des ersten (links stehenden) Befehls aus. Nur wenn dieser gleich Null ist – nur das signalisiert eine fehlerfreie Befehlsausführung – wird der zweite Befehl gestartet.
Achtung: das doppelte Ampersand-Zeichen darf nicht mit dem einfachen verwechselt werden. Dies hat eine ganz andere Funktion: es bewirkt, dass der links davon angegebene Befehl im "Hintergrund" ausgeführt wird. (Mehr dazu in einer der nächsten Folgen dieser Serie.)
Übrigens gibt es auch eine einfache Möglichkeit, auf Fehler bei der Befehlsausführung zu reagieren. Durch ein doppeltes Pipe-Symbol (das auch wiederum nichts mehr mit Pipes zu tun hat), wird der zweite Befehl nur dann ausgeführt, wenn der erste einen von Null verschiedenen Rückgabewert lieferte:
$> ls /root/ || echo Oh no! ls: /root/: Keine Berechtigung Oh no!
Da der User (normalerweise) über keine Berechtigung zum Auslesen des Homeverzeichnisses von Root (/root/) verfügt, kann der ls-Befehl nicht erfolgreich beendet werden. Er erzeugt daher beim Ende einen Rückgabewert von "1". Dieser veranlasst die Shell, aufgrund des "||"-Operators nun den zweiten Befehl auszuführen. (agr)
Ausblick: Funktionen und Scripts
Die bisher vorgestellten Befehlsfolgen sind noch recht einfacher Natur. Für viele (ca. 70%) aller Probleme reichen sie aber schon aus. In einer der nächsten Folgen dieser Serie werden die weitaus mächtigeren Funktionen und Scripte vorgestellt.



