Piping und Redirection bash Tutorial Teil 18

In vergangenen Teilen habe ich von Piping schon öfters Gebrauch gemacht. Zeit, es mal zu erklären.

Dr. Dirk Colbry, Michigan State
Gnu-bash-logoCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=
1Einführung
2Der bash Prompt
3key bindings
4Der Startvorgang
5Environment Variablen
6builtin commands
7Arbeiten mit Dateien
8nano
9bash Scripting
10Variablen
11Verzweigungen (if)
12Schleifen
13Kommandozeilenparameter
14exit Codes bash Tutorial Teil 14
15von der Idee zum Script
16grep
17Piping und Redirection
18tee

Eingabe- und AusgabeKanäle

Die bash hat drei verschiedene Kanäle ( Streams), die sich für die Eingabe- und Ausgabe von Daten zuständig sind.

Da ist zunächst stdin. Dies ist der Regel die Tastatur

Die Standardausgabe wird über stdout abgewickelt. Dieser Kanal ist meistens mit der Console verbunden. Hier landet alles, was ein Programm ausgibt, abgesehen von Fehlermeldungen.

stderr arbeitet ähnlich wie stdout, allerdings sollen hier nur Fehlermeldungen erscheinen. Üblicherweise ist dieser Kanal auch mit der Console verbunden. Könnte allerdings auch z.B. in eine Datei oder auf den Drucker umgelenkt werden.

Redirection

Das Umlenken (Redirection) von Kanälen habe ich schon früher benutzt.Der häufigste Anwendungsfall ist wohl, die Ausgabe eines Programms in einer Datei zu speichern, um sie für die spätere Auswertung zur Verfügung zu haben. Das probieren wir direkt mal praktisch aus. Um stdout in eine Datei umzulenken, benutzt du das „größer als“ Zeichen gefolgt vom Dateinamen.

ls -l / > ls.txt

Dabei wird eine neue Datei ls.txt angelegt und alles, was das ls Kommando ausgibt, in diese Datei hineingeschrieben. Das birgt eine gewisse Gefahr mit sich, da eine bereits vorhandene Datei überschrieben wird. In ls.txt findest du genau das wieder, was ls ausgegeben hat, während auf der Console nichts zu sehen ist.

cat ls.txt

Es gibt auch die Möglichkeit, den ausgegebenen Text an eine bestehende Datei anzuhängen. Dazu benutzt zwei „größer als“ Zeichen direkt hintereinander schreibst.

for i in {1..3}; do
    ls -al >> ls.txt
done

In diesem Fall wird ls.txt nicht bei jedem Aufruf von ls neu angelegt sondern in jedem Schleifendurchlauf wird die Ausgabe von ls an die bestehende Datei hinten angehängt.

Unerwünschten Output umleiten

Wenn ein Kommando, das du in deinem Script verwendest, Ausgaben nach stdout schreibt, die du nicht sehen möchtest, kannst du diese loswerden, in dem du du stdout nach /dev/null umleitest. Das Null-Device ist ein besonders File, dass alles, was du hinleitest, einfach verwirft.

ls -l / > /dev/null

Dieser Aufruf von ls wird nichts ausgeben, da die gesamte Ausgabe in /dev/null verschwindet.

Durch das Anhängen der Ausgabe findet grep das backup Verzeichnis dreimal.
Olli Graf - raspithek.de
redirection-appendCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=
Durch das Anhängen der Ausgabe findet grep das backup Verzeichnis dreimal.

Jetzt achte mal darauf, was passiert, wenn ich ls auf ein nicht existierendes Verzeichnis aufrufe:

ls -l ~/foo > ls.txt
ie Fehlermeldung von ls wird nicht in die Datei geschrieben, sondern auf der Console ausgegeben.
Olli Graf - raspithek.de
ls -l fooCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=
Die Fehlermeldung von ls wird nicht in die Datei geschrieben, sondern auf der Console ausgegeben.

Du erkennst, dass die Fehlermeldung auf der Console erscheint. Die Ausgabedatei ist leer, da ls wegen des Fehlers nichts in stdout geschrieben hat. Die Fehlermeldung wird nach stderr geschrieben. Da der Kanal nicht umgeleitet wird, steht die Fehlermeldung nicht in der Datei.

Es gibt aber eine Möglichkeit, stderr nach stdout um zu leiten.

ls -l ~/foo 2>ls.txt >ls.txt

Die Fehlermeldung steht jetzt in ls.txt.Die 2 bezeichnet die Kanalnummer: stdin = 0, stdout = 1, stderr = 2

Du kannst auch stderr nach stdout umleiten.

ls -l ~/foo 2>&1

Beim Ausführen wirst du keinen Unterschied erkennen, da stderr per Voreinstellung auch auf die Console ausgibt.

Piping

Daten fließen durch eine Röhre
Daten fließen durch eine Röhre (generiert von DALL-E)

Eine Pipe (dt. Röhre) leitet Ausgabedaten des einen Programms von stdout nach stdin eines anderen Programms weiter. Ich habe dieses Verfahren schon häufig benutzt, da es eins der wichtigsten Features einer Shell ist. Zum Piping benutzt du den „senkrechten Strich“ (AltGr > auf einem Standard PC Keyboard). Ich nenne den senkrechten Strich inzwischen eigentlich fast nur noch Pipe.

Die Datei ls.txt kannst du dir mit cat anzeigen lassen.

cat ls.txt

Das ist nicht Neues. Aber den Umweg über die Datei kannst du dir sparen mit einer Pipe.

ls -l / | cat
Olli Graf - raspithek.de
ls -l | catCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=

Was passiert hier? Das ls Kommando wird ausgeführt, doch statt nach stdout zu schreiben, landet das Directorylisting durch die Pipe direkt in stdin von cat, dass die Daten nach stdout ausgibt. Das macht in diesem Fall natürlich gar keinen Sinn. Sehr viel nützlicher ist es, wenn das Kommando, in das hinein gepiped wird, etwas mit den empfangenen Daten tut, wie z.B. grep oder sort.

So kannst du mit grep in langen Verzeichnislisten einfach die Zeile herausfiltern, die dich interessiert.

ls -l / | grep boot

Die Ausgabe von ls wird nach grep gepiped, dass nur noch Zeilen durchlässt, die den String boot enthalten.

Durch die Pipe erscheinen nur noch die beiden Verzeichnisse, die den String "boot" enthalten.
Olli Graf - raspithek.de
ls-l|grepCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=
Durch die Pipe erscheinen nur noch die beiden Verzeichnisse, die den String“ boot“ enthalten.

Übrigens: Ob du das Pipesymbol mit Leerzeichen umgibst, ist unwichtig, ich mache das hier nur zur besseren Lesbarkeit.

Du kannst den Output von grep auch direkt in das nächste Kommando pipen und eine lange Kette von Pipes aufbauen.

Im nächsten Teil werden wir das Piping mit dem tee Kommando weiterführen.

Schreibe einen Kommentar

Creative Commons License
Except where otherwise noted, the content on this site is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
Olli Graf - raspithek.de
WordPress Cookie Hinweis von Real Cookie Banner