Kombination von Befehlen
Übersicht über das Konsolen-Tutorial
Vorbemerkung
Eine der Stärken des Nutzens einer Konsole ist die Möglichkeit, die hochspezialisierten Einzelkommandos zu kombinieren.
Dateiumleitung
Viele Programme verwenden nur einen Eingabe- und einen Ausgabekanal, genannt stdin und stdout. Standardmäßig ist der Eingabekanal mit dem Eingabebereich der Shell verbunden, der Ausgabekanal mit der Ausgabe der Shell.
Mit dem Zeichen '>' wird der Ausgabekanal in die Datei umgeleitet, die dem '>' folgt. Ein '>>' erzeugt keine neue Datei, wenn schon eine existiert, sondern hängt den Inhalt an den vorhandenen.
Mit dem Zeichen '<' wird der Eingabekanal mit dem Inhalt der Datei "gefüttert", deren Name dem '<' folgt.
Hinweis: Es gibt da noch stderr, aber das gehört nicht zum Grundkurs.
Beispiel
cat ist ein Programm, das von stdin liest und nach stdout ausgibt. Rufen wir cat ohne Parameter auf, geht der Cursor in die nächste Zeile und dann passiert scheinbar gar nichts. Der Grund ist, das Programm wartet auf Eingaben. Wir geben z.B. "Zeile 1" ein und drücken Enter. Sofort wird genau dieser Text "Zeile 1" nochmal ausgegeben, denn cat gibt ja alles, was auf stdin hereinkommt, wieder auf stdout (also auf die Konsole) aus. Wenn wir cat signalisieren wollen, dass die Eingabe beendet ist, müssen wir das Spezialzeichen Strg-d ("Dateiende") am Zeilenanfang eingeben. Dann beendet sich cat.
Wir leiten jetzt den Ausgabekanal in die Datei "test.txt" um:
cat >test.txt
Wieder erscheint der Cursor in der nächsten Zeile, das Programm wartet auf Eingabe.
Wir geben ein: "Zeile 1", Enter, "Zeile 2", Enter, Strg-d Diesmal wiederholt cat den eingegeben Text nicht, denn der Ausgabekanal ist ja die Datei test.txt. Dort findet sich der eingegebene Text.
Jetzt noch der umgekehrte Weg: Wir leiten den Inhalt der Datei in das Programm cat, das diesen dann ausgibt:
cat <test.txt
Zeile 1 Zeile 2
Anwendungsbeispiel
Wir wollen uns merken, wie die Partitionstabellen aller Festplatten aussehen, um bei einem Schadensfall diese evt. reparieren zu können. Das Programm fdisk zeigt uns diese Daten an. Um sie aufzuheben, leiten wir die Ausgabe in eine Datei um:
fdisk -l > ~/partitionen_2011_09_08.txt
Hinweis: fdisk funktioniert nur als root.
Here-Dokument
Wenn nur Text, aber keine Datei vohanden ist, aber das Programm eine Datei braucht (als Eingabe), hilft das Here-Dokument: Anstelle der Datei wird <<MARKE eingesetzt. Alle Zeilen nach dem Kommando bis zu der Zeile, die nur aus MARKE besteht, gehören dann zum Here-Dokument. Dies ist vor allem bei Tutorials und in Scripts nützlich.
Beispiel
cat <<EOS >hits_of_deep_purple.txt
Child in Time
Smoke on the Water
Highway Star
EOS
Damit ist ganz schnell die Datei hits_of_deep_purple.txt mit Text gefüllt.
Wird die Form <<'MARKE' verwendet, erfolgt keine Expansion von Shell-Variablen, ein '$' wird also als '$' ausgegeben.
cat <<'EOS' >readme.txt
Ein Dollar ('$') ist das Symbol für die US-Währung.
EOS
Verkettung (Pipelining)
Soll die Ausgabe eines Programms die Eingabe eines anderen Programmes sein, so geht dies mit dem Zeichen '|'. Dies kann zwar auch mit Dateiumleitung erreicht werden, ist aber so viel einfacher und braucht auch keinen Plattenplatz (ist bei großen Datenmengen ein wichtiger Grund).
Folgende Konstrukte sind (bis auf den Platzbedarf) äquivalent:
ls -1 >/tmp/dateien
wc -l </tmp/dateien
Das Kommando "ls -1" listet alle Dateien des aktuelle Verzeichnisses auf, jede Datei in einer Zeile. Das Kommando wc -l zählt die Zeilen der Eingabe. Das Ergebnis ist die Anzahl der Dateien im aktuellen Verzeichnis.
Jetzt das ganze mit Verkettung:
ls -1 | wc -l
Ist das nicht kurz und bündig?
Hinweis: Die Option von ls ist die Zahl 1, die Option von wc ist der kleine Buchstabe l.
Eine Verkettung kann beliebig oft erfolgen:
cat a.txt a.txt b.txt | sort | uniq -u | grep "[0-9]"
Diese Kette findet alle Zeilen von a.txt, die nicht in b.txt vorkommen und die mindestens eine Dezimalziffer enthalten.
Der Trick ist, dass durch die doppelte Angabe von a.txt in cat jede Zeile von a.txt zweimal in der Ausgabe vorkommt.
Steht eine Zeile in a.txt und in b.txt, kommt sie in der Ausgabe 3 mal vor, steht sie nur in a.txt, kommt sie 2 mal vor. Einzelzeilen müssen daher aus b.txt stammen und nicht in a.txt stehen.
uniq -u gibt nur die Zeilen aus, die genau einmal vorkommen (genauer kein Doppel davor oder danach haben). Wegen der letzen Einschränkung muss ein sort davorgeschaltet werden, das die Eingabe sortiert.
Bedingte Ausführung
Manchmal ist es sinnvoll, einen Befehl auszuführen, wenn der vorausgehende Befehl erfolgreich war. Das wird mit dem Symbol '&&' erreicht:
mount /media/usb && rsync -a /home /media/usb
Das Heimatverzeichnis wird nur dann auf den USB-Stick gesichert, wenn dieser erfolgreich eingebunden werden konnte.
In anderen Fällen ist es sinnvoll, einen Befehl nur dann auszuführen, wenn der vorausgehende Befehl nicht erfolgreich war. Das wird mit dem Symbol '||' erreicht:
cp -a /etc ~/backup || echo "Problem beim Kopieren von /etc" >>~/log/backup.txt
Wenn das Kopieren des Dateibaums von /etc einen Fehler aufwies, wird eine Meldung an eine Logdatei angehängt.
Befehlsliste
Es können auch mehrere Befehle in eine Zeile geschrieben werden, das Trennzeichen ist dann ';'
pushd /etc; tar czf /tmp/etc.tgz * ; popd
Verzeichnis wird gespeichert und ins Verzeichnis /etc gegangen, ein Tar-Archiv erzeugt und das vorige Verzeichnis restauriert.