Dieser Artikel ist größtenteils für alle Ubuntu-Versionen gültig.
Beim Arbeiten im Terminal bietet die Bash verschiedene Möglichkeiten, die Ausgabe der einzelnen Befehle umzuleiten bzw. an andere Befehle weiterzuleiten. Ebenso besteht die Möglichkeit, dass Befehle, die standardmäßig von der Standardeingabe lesen, alternativ die Eingabe(n) aus einer Datei lesen.
Dieser Wiki-Beitrag bezieht sich primär auf die Bash. Die Umleitungen > , < und | stehen in anderen POSIX-kompatiblen Shells jedoch in gleicher Form zur Verfügung.
Vorab noch ein wenig Hintergrundwissen: Alle Befehle und Programme, welche in der Bash gestartet werden, erhalten drei Kanäle zugewiesen:
Den Standardeingabekanal stdin, dieser hat die Nummer 0 (null). Normalerweise liest stdin Eingaben von der Tastatur, welche mit dem Terminal verbunden ist.
Den Standardausgabekanal stdout, dieser hat die Nummer 1 (eins). Normalerweise schreibt stdout Ausgaben auf den Bildschirm, welcher mit dem Terminal verbunden ist.
Den Standardfehlerkanal stderr, dieser hat die Nummer 2 (zwei). Normalerweise schreibt stderr Ausgaben auf den Bildschirm, welcher mit dem Terminal verbunden ist.
Mit Hilfe des "Größer als" Zeichens > lässt sich die Standardausgabe stdout umleiten. Eine typische (und sehr häufige) Anwendung ist das Umleiten in eine Datei. So schreibt zum Beispiel der Befehl
ls > verzeichnis.txt
den Inhalt des aktuellen Verzeichnisses in die Datei verzeichnis.txt anstatt in das Terminal.
Existiert die Datei verzeichnis.txt nicht, so wird diese angelegt. Existiert die Datei bereits, so wird diese ohne Rückfrage überschrieben!
Aus demselben Grund funktioniert beispielsweise auch sed s/muster/ersetzungstext/ < datei.txt > datei.txt
nicht. Da die Öffnung des umgeleiteten Ausgabekanals - die damit einhergehende Löschung des Inhalts von datei.txt - der Öffnung des Eingabekanals vorausgeht, arbeitet sed
mit einer leeren Datei.
Es ist aber auch möglich, die Ausgabe an existierende Dateien anzuhängen, in dem man statt ein > zwei >> verwendet. Der Befehl
ls ~/Desktop >> verzeichnis.txt
hängt den Inhalt von ~/Desktop also an die Datei verzeichnis.txt an.
Neben stdout schreibt auch der Standardfehlerkanal stderr regelmäßig auf das Terminal. Möchte man die Ausgabe von stderr umleiten, muss man 2>
statt >
verwenden:
ls -la /home/user 2> fehler.txt
2>
heißt soviel wie „leite den Kanal 2 (stderr) um“.
Der Kanal 1 (stdout) muss bei der Umleitung nicht explizit benannt werden. ">" wird von der Bash automatisch mit "1>" gleichgesetzt.
Es lassen sich auch beide Kanäle gleichzeitig in zwei verschiedene Dateien umleiten:
ls -la > verzeichnis.txt 2> fehler.txt
So wird die Ausgabe von ls in die Datei verzeichnis.txt umgeleitet, Fehlermeldungen in die Datei fehler.txt. Weiterhin ist es auch möglich, beide Kanäle in eine Datei zu leiten:
ls -la > gemeinsam.txt 2>&1
2>&1
bedeutet also soviel wie „schreibe die Ausgabe von Kanal 2 (stderr) dorthin, wo die Ausgabe von Kanal 1 (stdout) geschrieben wird“.
Die Reihenfolge ist wichtig: Es wird immer dorthin umgeleitet, wohin der angegebene Kanal gerade geleitet wird. Stellt man das 2>&1
also vor das > gemeinsam.txt
, wird stderr auf die Standardausgabe geleitet, nur was ursprünglich auf die Standardausgabe geschrieben wurde, landet in der Datei.
Natürlich kann man auch bei Kanal 2 zwei größer-als-Zeichen verwenden. So lassen sich z.B. Fehlermeldungen während einer Datensicherung von Tar an eine Logdatei anhängen:
echo "Sicherung" >> backup.log tar -cf sicherung.tgz "/home" 2>> backup.log
Die Verwendung von &> leitet sowohl stdout als auch stderr in die angegebene Datei um. Das ist hilfreich u.a. in Bash-Skripten, in denen lediglich der Rückgabewert von Befehlen interessiert, nicht aber der Ausgabetext. Dieses Beispiel beendet ein Skript, wenn irgendeine Datei im Homeverzeichnis geöffnet ist und unterdrückt dabei jegliche Ausgaben:
1 2 3 | if lsof ~ &>/dev/null; then exit 1; fi |
In alten Versionen der Bash funktionierte die Umleitung mit &>>
nicht. Abhilfe schafft das Anhängen von stdout an eine Datei anhängen und die Umleitung von stderr nach stdout. Dieses Beispiel führt ein Kommando aus und hängt sowohl stdout als auch stderr an ein logfile:
./my_command.sh >> results.log 2>&1
Innerhalb eines Skripts lässt sich die Ausgabe auch global umleiten. Mit
exec > datei.txt
sowie sämtlicher in diesem Abschnitt genannten Varianten wird die Ausgabe aller nachfolgenden Befehle in die Datei geschrieben. Eine explizite Umleitung ist dann in den Befehlen nicht mehr erforderlich.
Mit Hilfe des „Kleiner als“-Zeichens < lässt sich die Standardeingabe (stdin) umleiten. Beispiel:
tr -d '0-9' < datei.txt
Dieser Aufruf zeigt den Inhalt aus datei.txt ohne Ziffern an.
Bei Verdoppelung des Zeichens << kann man auf der Standardeingabe auch eine Pseudodatei erzeugen (sogenanntes Hier-Dokument), die dann sequenziell gelesen wird. Hinter dem Zeichen ist ein Schlüsselwort einzugeben, welches das „Dateiende“ symbolisiert. Beispiel:
while read d do touch $d done << eod aufdieplaetze.txt fertig.txt los.txt eod
In dem Beispiel werden in einem Durchgang drei Dateien mit den im Hier-Dokument enthaltenen Namen erzeugt.
Der Pipe-Operator (Pipe = Kurzform für Pipeline) leitet die Ausgabe eines Befehls direkt an einen anderen Befehl weiter (anstatt ins Terminal). Damit kann der zweite Befehl das Ergebnis bzw. die Ausgabe des ersten Befehls weiterverarbeiten. Die allgemeine Syntax lautet (man kann natürlich auch mehr als zwei Befehle miteinander verbinden):
Befehl1 | Befehl2
Das Zeichen für den Pipe-Operator |
erhält man auf einer deutschen Tastatur durch Drücken von
Alt Gr +
< .
Eine typische Anwendung für den Pipe-Operator ist z.B. das Ausrufen eines Befehls, der eine größere Menge an Daten auf stdout schreibt (z.B. Ausgaben von Systemmeldungen wie dmesg
oder Ausgaben von Prozessinformationen wie ps und pstree) in Kombination mit Datensortierung (z.B. sort
) oder Durchsuchen der Ausgabe nach bestimmten Ausdrücken (z.B. grep). Einige Beispiele:
Im ersten Beispiel werden alle laufenden Prozesse durch ps
ausgegeben, der Pipe-Operator leitet die Ausgabe an sort
weiter. sort
sortiert die Daten um (absteigende numerische Sortierung, Option -nr
) und gibt die umsortierten Daten dann an stdout weiter.
ps ax | sort -nr
Im zweiten Beispiel gibt dmesg
alle Log-Meldungen des Kernels aus, der Pipe-Operator leitet diese an grep
weiter. grep
sucht nur nach Zeilen, in denen der Ausdruck usb
vorkommt. Die Ausgabe von grep
erfolgt dann (standardmäßig) auf stdout (der Parameter -n
sorgt dafür, dass grep die Zeilen nummeriert).
dmesg | grep -n USB
Im dritten Beispiel kommen mehrere Pipelines zum Einsatz. Das zweite Beispiel wird durch einen weiteren Pipe-Operator und den Befehl tail
ergänzt. Somit werden nur noch die letzten zehn Zeilen angezeigt.
dmesg | grep -n USB | tail
Natürlich lässt sich der Pipe-Operator auch mit der Umleitung von stdin und stdout kombinieren, zum Beispiel:
grep usb < alle-meldungen.log | tail > usb-meldungen.log
Die Umleitungen müssen übrigens nicht hinter dem Befehl stehen, sie können auch davor oder mittendrin geschrieben werden:
grep < alle-meldungen.log usb | >usb-meldungen.log tail
Das Programm tee liest von der Standardeingabe stdin und verdoppelt die eingelesenen Daten. Die Daten werden dann je einmal an eine Datei und an die Standardausgabe stdout weitergeleitet. tee ist im essentiellen Paket
coreutils
von Ubuntu enthalten und ist deshalb auf jedem System installiert.
Die allgemeine Syntax lautet:
tee [OPTIONEN] Ausgabedatei
tee kennt die folgenden Optionen:
tee - Optionen | |
Option | Beschreibung |
-a oder --append | Die Daten aus der Standardeingabe stdin werden an die Ausgabedatei angehängt, anstatt diese zu überschreiben. |
-i oder --ignore-interrupts | Interrupt-Signale werden ignoriert. |
--help | Zeigt Hilfsinformationen zu tee an. |
--version | Zeigt die Versionsnummer von tee an. |
Üblicherweise wird tee in einer Pipe verwendet, wie z.B.:
ls -la | tee alle_dateien.txt | grep '\.png$'
Es wird das ausführliche Inhaltsverzeichnis angezeigt, einmal (vollständig) in die Datei alle_dateien.txt geschrieben und einmal an grep
weitergeleitet, welches nur alle png-Dateien auf stdout ausgibt.
script - Terminalsitzung mitschneiden
Shell/Befehlsübersicht Übersicht über verschiedene Shell-Befehle
Diese Revision wurde am 13. Juli 2015 09:01 von wxpte erstellt.