Die Shell hilft, wenn es um kniffelige Probleme geht. Genügen die Fähigkeiten eines einzelnen Tools nicht Ihren Wünschen, verketten Sie einfach mehrere Kommandos.
Auf gute Zusammenarbeit – wer Shell-Befehle miteinander kombiniert, spielt die ganze Stärke der Kommandozeile aus. Dazu gehört nicht nur das Verketten einzelner Programme, sondern auch das Weiterleiten der Ausgaben: Scrollen die Informationen zu schnell über den Bildschirm, leiten Sie diese einfach in eine Datei um oder zeigen Sie seitenweise an.
Gut kombiniert
Mit wenigen Handgriffen verknüpfen Sie in der Bash einzelne Befehle miteinander. Anstelle der Sequenz aus den Zeilen 1 bis 3 von Listing 1 kombinieren Sie die einzelnen Arbeitsschritte und teilen dem Interpreter über das Semikolon mit, dass er alle Befehle direkt hintereinander ausführen soll (Zeile 4).
Listing 1
$ mkdir Ordner $ cd Ordner $ cp ../Ordner2/* . $ mkdir Ordner; cd Ordner; cp ../Ordner2/* .
Noch mehr Kontrolle erhalten Sie, indem Sie der Bash eine Bedingung stellen. So ist es beispielsweise möglich, einen zweiten (oder dritten oder n-ten) Befehl nur dann auszuführen, wenn ein anderes Kommando erfolgreich oder nicht erfolgreich war.
Um beispielsweise eine bestimmte Datei nur dann zu löschen, wenn sie auch tatsächlich vorhanden ist, stellen Sie dem Kommando Rm einen einfachen Test voran:
$ test -w Datei && rm Datei
Das gleichnamige Programm Test sieht in diesem Fall nach, ob die Datei existiert und beschrieben werden darf (Parameter -w). Nur, wenn das der Fall ist, löscht Rm das File.
Bauen Sie häufig Software aus den Quellen und setzen dabei den Dreierschritt ./configure; make; sudo make install ein, können Sie alle drei Befehle miteinander kombinieren und durch && sicherstellen, dass jeder folgende Befehl nur weitermacht, wenn der Vorgänger keine Fehler produziert hat:
$ ./configure && make && sudo make install
Neben der Option -w hat das Kommando Test noch einige weitere praktische Schalter zu bieten. So sehen Sie zum Beispiel mit -d nach, ob ein Verzeichnis schon existiert, und erstellen es nur dann, wenn das nicht der Fall ist:
$ test -d Ordner || mkdir Ordner
Dabei übernehmen die zwei Pipe-Zeichen zwischen den Befehlen die Funktion eines logischen Oder.
Kanalsystem
Für die Ein- und Ausgabe von Befehlen auf der Shell gibt es drei sogenannte Kanäle: Programme lesen Ihre Daten von der Standardeingabe (stdin, Kanal 0) oder aus einer Datei. Seine Ausgaben schreibt das Programm auf die Standardausgabe (stdout, Kanal 1). Fehlermeldungen schließlich landen auf der Standardfehlerausgabe (stderr, Kanal 2):
Befehl < Eingabe > Ausgabe 2> Fehler
Die Operatoren < und > verraten dabei die Richtung: Erfolgt die Standardeingabe nicht über die Tastatur, dann sorgt < dafür, dass der Befehl sie beispielsweise aus einer Datei einliest. Um hingegen die Ausgabe eines Kommandos in eine Datei umzuleiten, dient der Operator >.
Die Fehlerausgabe erreichen Sie ebenfalls über >. Allerdings spezifizieren Sie hier den Kanal durch Voranstellen des File Descriptors (2>). Die Tabelle “Shell-Umleitungen” zeigt eine Übersicht der gebräuchlichsten Umleitungsszenarien, und die folgenden Abschnitte zeigen detaillierte Anwendungsbeispiele.
Shell-Umleitungen
| Kanal | Kommando | Ergebnis |
|---|---|---|
1 (stdout) |
Befehl > Datei |
schreibt die Standardausgabe von Befehl in Datei |
1 (stdout) |
Befehl >> Datei |
hängt die Standardausgabe von Befehl an Datei an |
2 (stderr) |
Befehl 2> Datei |
lenkt die Standardfehlerausgabe von Befehl in Datei um |
2 (stderr) |
Befehl 2>> Datei |
hängt die Standardfehlerausgabe von Befehl an Datei an |
1 und 2 (stdout, stderr) |
Befehl > Datei 2>&1 |
schreibt Standardausgabe und Standardfehlerausgabe von Befehl in dieselbe Datei |
1 und 2 (stdout, stderr) |
Befehl > Datei 2> Datei2 |
Standardausgabe von Befehl landet in Datei, die Standardfehlerausgabe in Datei2 |
0 (stdin) |
Befehl < Datei |
leitet Datei in Standardeingabe von Befehl um |
Ausgabe umleiten
Wie schon erwähnt, leitet der Operator > die Ausgabe eines Programms in eine Datei um. Anstelle von > könnten Sie auch 1> schreiben, denn es handelt sich ja um den ersten Kanal; zwingend nötig ist die Angabe aber nicht, denn ohne weitere Angaben verwendet die Shell immer die Standardausgabe:
$ ls /etc > etc_inhalt.txt
Existiert die Datei hinter dem Operator bereits, überschreibt die Shell sie einfach. Einen Ausweg aus der Misere bietet der bereits gezeigte Test oder das Verdoppeln des Operators:
$ test -w etc_inhalt.txt || ls /etc > etc_inhalt.txt $ ls /etc >> etc_inhalt.txt
Die zwei Größer-Zeichen im zweiten Kommando bedeuten im Klartext, dass die Shell die Ausgabe des Befehls Ls an die Datei etc_inhalt.txt anhängt, falls diese schon existiert. Falls nicht, erzeugt das die Datei neu und schreibt die Ausgabe hinein.
Fehlermeldungen abfangen
Den Kanal stderr leiten Sie um, indem Sie die Ziffer 2 vor den Operator > stellen. Das bietet sich vor allem dann an, wenn die Fehlermeldungen eines Programms so zahlreich über das Terminal fliegen, dass sie Sie beim Lesen der anderen Ausgaben stören (Listing 2).
Listing 2
$ find /home -name "*.tex" find: /home/lost+found: Keine Berechtigung find: /home/petronella/daten: Keine Berechtigung /home/huhn/buch/buch.tex /home/huhn/buch/kap01.tex [...]
Über das folgende Kommando schicken Sie die Fehlermeldungen an das Datengrab /dev/null auf dem Rechner:
$ find /home -name "*.tex" 2> /dev/null
Durch die Umleitung in das berühmt-berüchtigte “Nulldevice” landen die Fehlermeldungen im Nirwana, anstatt die Standardausgabe zu verunzieren.
Zwei auf einen Schlag
Ein geschicktes Kombinieren der Operatoren ermöglicht es darüber hinaus, zwei Kanäle gleichzeitig umzuleiten. Möchten Sie die Standardausgabe des eben gezeigten Find-Befehls in eine Datei schreiben, ohne dabei auch sämtliche Fehlermeldungen zu protokollieren, schreiben Sie einfach:
$ find /home -name "*.tex" > findausgabe 2> /dev/null
Der doppelte Operator >>, der nicht existierende Dateien erstellt oder an bestehende Files anhängt, darf auch in diesem Szenario zum Einsatz kommen. Wie das für die Standardausgabe geht, haben Sie schon gesehen. Auf die gleiche Weise setzen Sie den Doppelpfeil bei der Standardfehlerausgabe ein:
$ find /home -name "*.tex" > findausgabe 2>> fehler
Dieses Kommando sorgt dafür, dass die eigentlichen Ausgaben des Kommandos in der Datei findausgabe landen, die Fehlermeldungen jedoch in einem File namens fehler.
Röhrensystem
Mit sogenannten Pipes sparen Sie oft weitere Arbeitsschritte ein, indem Sie die Ausgabe eines Befehls direkt an ein anderes Programm weiterleiten, ohne den Umweg über das Umleiten in eine Datei. Dabei steht das Pipe-Zeichen ([AltGr]+[<]) zwischen den einzelnen Befehlen, wie das folgende Beispiel verdeutlicht:
$ ls /etc | less
Die Ausgabe von Ls erscheint nun nicht mehr im Terminal, sondern direkt im Pager Less, der sie seitenweise anzeigt und so das bequeme Auf- und Abblättern ermöglicht. Besonders häufig kommt die Pipe auch zum Einsatz, um eine bestimmte Ausgabe mit Grep zusammen nach Zeichenketten zu durchsuchen, zum Beispiel:
$ find debian -name "*.png" | grep --color apt
Dieses Kommando fahndet im Ordner debian zunächst nach allen Dateien, die auf .png enden, und leitet die Ausgabe direkt an Grep weiter. Das sucht nach der Zeichenkette apt und färbt die Treffer dank der Option --color Rot ein (Abbildung 1).
Auch dem Einsatz mehrerer Pipes steht nichts entgegen. Der folgende Befehl listet den Inhalt Ihres Home-Verzeichnisses einzeilig auf, leitet das Ergebnis wieder an das Programm Grep weiter, sucht nach der Zeichenkette .jpg, und zählt anschließend die Treffer:
$ ls -1 ~ | grep .jpg | wc -l 12
So finden Sie also ohne langes Suchen heraus, dass sich zwölf JPG-Dateien direkt im Home-Verzeichnis befinden.
Zeit für Tee?
Zwischen die einzelnen Pipe-Stücke bauen Sie mit dem Programm tee einen Abzweig ein. Das Kommando erwartet Daten aus der Standardeingabe und schreibt sie sowohl in eine Datei als auch auf den Bildschirm. Ein solches T-Stück darf ganz am Ende oder zwischen den einzelnen Befehlen stehen:
$ Befehl1 | tee ausgabe.txt | Befehl2
Um beispielsweise ausgehend vom aktuellen Verzeichnis nach PNG-Dateien zu suchen und diese Ausgabe sowohl in der Datei bilder.txt zu protokollieren als auch anzuzeigen und mit Grep nach der Zeichenkette buch zu durchstöbern, tippen Sie:
$ find . -name "*.png" | tee bilder.txt | grep buch
Standardmäßig überschreibt Tee die angegebene Zieldatei, falls diese bereits existiert. Um Ausgaben an ein bereits vorhandenes Protokoll anzuhängen, steht der Aufrufparameter -a bereit:
$ find . -name "*.png" | tee -a bilder.txt | grep buch
Die verschiedenen Operatoren sowie die Pipe und der Befehl Tee ermöglichen also ein sehr flexibles Kombinieren von Shell-Kommandos. Für eine schnelle Suche beispielsweise lohnt sich daher meist nicht der Aufwand, ein komplettes Skript zu schreiben. Bei regelmäßigem Einsatz fließen Ihnen die Kombinationen ohnehin wie selbstverständlich aus den Fingern.






