Tracks
/
Bash
Bash
/
Lehrplan
/
Umleitung
Um

Umleitung in Bash

{one: "1 Übung", other: "%{count} Übungen"}

Über Umleitung

In der Welt der Kommandozeile arbeiten Programme oft mit drei Standard-Datenströmen:

  1. Standardeingabe (stdin): Hier empfängt ein Programm seine Eingabe (normalerweise von der Tastatur).
  2. Standardausgabe (stdout): Hierhin schickt ein Programm seine normale Ausgabe (normalerweise auf den Terminalbildschirm).
  3. Standardfehlerausgabe (stderr): Hierhin schickt ein Programm Fehlermeldungen (normalerweise auf den Terminalbildschirm).

Erinnere dich daran, dass wir diese im Kapitel Pipelines und Befehlslisten eingeführt haben.

Note

Pipelines kann man als eine Form der Umleitung betrachten: Die Standardausgabe eines Programms wird direkt an die Standardeingabe eines anderen geschickt. Pipelines haben wir bereits behandelt. In diesem Konzept geht es um die Umleitung in und aus Dateien.

Die Shell-Umleitung ist ein mächtiger Mechanismus, mit dem du das Ziel dieser Ströme änderst. Statt dass ein Programm von der Tastatur liest oder auf den Bildschirm schreibt, kannst du die Eingabe aus einer Datei umleiten oder die Ausgabe in eine Datei schicken. Das gibt dir viel Flexibilität und Kontrolle darüber, wie Programme mit Daten umgehen.

Wichtige Umleitungsoperatoren

Hier sind die gebräuchlichsten Umleitungsoperatoren und was sie bewirken:

> (Ausgabeumleitung)

  • Zweck: Die Standardausgabe (stdout) eines Befehls in eine Datei umleiten.

  • Verhalten:

    • Wenn die Datei nicht existiert, wird sie angelegt.
    • Wenn die Datei existiert, wird ihr Inhalt überschrieben.
  • Beispiel:

    # Sends the output of 'ls -l' to 'file_listing.txt'
    ls -l > file_listing.txt
    
Caution

Die Umleitung erfolgt bevor der Befehl ausgeführt wird. Das bedeutet, du kannst nicht in dieselbe Datei umleiten, aus der du lesen musst.

date > date.txt         # populate the file with the current date
cat date.txt > date.txt # 'date.txt' is now empty!

Im zweiten Befehl des obigen Beispiels

  1. kürzt Bash zuerst die in der Umleitung angegebene Datei. Dadurch wird der bisherige Inhalt zerstört, und es bleibt eine leere Datei übrig.
  2. Dann liest Bash die nun leere Datei.
  3. Dann schreibt Bash den Inhalt (also nichts) zurück in die Datei.

>> (Ausgabe anhängen)

  • Zweck: Die Standardausgabe (stdout) eines Befehls an eine Datei anhängen.

  • Verhalten:

    • Wenn die Datei nicht existiert, wird sie angelegt.
    • Wenn die Datei existiert, wird die Ausgabe ans Ende der Datei angehängt.
  • Beispiel:

    # Adds "Another line" to the end of the file
    echo "Another line" >> file_listing.txt
    

< (Eingabeumleitung)

  • Zweck: Die Standardeingabe (stdin) eines Befehls aus einer Datei umleiten.

  • Verhalten: Der Befehl liest seine Eingabe aus der angegebenen Datei statt von der Tastatur.

  • Beispiel:

    # 'tr' reads from 'lowercase.txt' and
    # output is redirected to 'uppercase.txt'
    tr 'a-z' 'A-Z' < lowercase.txt > uppercase.txt
    

2> (Fehlerumleitung):

  • Zweck: Die Standardfehlerausgabe (stderr) eines Befehls in eine Datei umleiten.
  • Verhalten: Fehlermeldungen werden in die angegebene Datei geschrieben statt aufs Terminal.
  • Beispiel:
    # Error message from 'rm' is sent to 'error_log.txt'
    rm non_existent_file 2> error_log.txt
    

Mit 2>> kannst du die Standardfehlerausgabe an eine Datei anhängen.

Weitere Umleitungen

Es gibt auch Umleitungen, die stdin und stderr zusammenführen können. Details findest du im Handbuch.

/dev/null

/dev/null ist eine spezielle Datei, die

  • leer ist, wenn du daraus liest, und
  • alle Daten verwirft, die hineingeschrieben werden.

Man nennt sie manchmal auch „Bitbucket“. Sie ist nützlich, um Ausgaben oder Fehler zu unterdrücken.

some_command > /dev/null  # Discards stdout
some_command 2> /dev/null # Discards stderr

# Using /dev/null as input will prevent the command
# from reading data from the keyboard
some_command < /dev/null

Umleitungen kombinieren

Du kannst mehrere Umleitungen gleichzeitig angeben.

some_command < input.txt > output.txt 2> error.txt

Eine Umleitung kann kopiert werden.

# send stderr to the same destination as stdout
some_command > output.txt 2>&1

Wenn du 2>&1 siehst, lies das als „leite stderr dorthin um, wohin stdout gerade jetzt zeigt“. Bash verarbeitet Umleitungsanweisungen streng von links nach rechts. Das bedeutet, du kannst Folgendes machen:

# redirect stdout to 'output1.txt'
# redirect stderr to the same place
# then change stdout to 'output2.txt'
some_command > output1.txt 2>&1 > output2.txt
Advanced

Dateideskriptoren

In der Shell-Programmierung und in Betriebssystemen wie Linux/Unix ist ein Dateideskriptor (File Descriptor, FD) eine nicht-negative Ganzzahl, die als Kennung oder Handle für eine geöffnete Datei oder eine E/A-Ressource (Eingabe/Ausgabe) dient. Stell es dir wie ein Etikett oder eine Referenznummer vor, mit der das Betriebssystem den Überblick über geöffnete Dateien und Datenströme behält.

Die Zahlen, die du auf der linken Seite von Umleitungen siehst, sind Dateideskriptoren.

Die Standard-E/A-Ströme bekommen die ersten drei Dateideskriptoren:

  • Standardeingabe ist FD 0
  • Standardausgabe ist FD 1
  • Standardfehlerausgabe ist FD 2

Neue Dateideskriptoren kannst du mit dem Befehl exec und Umleitungsoperatoren setzen oder anlegen.

# create FD 3 as a copy of stdout
exec 3>&1
# send stdout to a log file
exec > log.txt

# then redirect both stdout and file descriptor 3
echo "some debug message" >&3  # displayed in the terminal
some_command  2>&1 # stdout and stderr send to 'log.txt'

Diese Technik wirkt ziemlich verschachtelt, aber sie kann sehr nützlich sein, wenn dein Skript von einer anderen Software ausgeführt wird und diese die Standardausgabe automatisch abfängt. Der Befehl bats, mit dem in diesem Track die Unit-Tests ausgeführt werden, funktioniert genau so: bats fängt die Standardausgabe und die Standardfehlerausgabe eines Tests ab, aber Debug-Meldungen an FD 3 werden auf dem Terminal angezeigt.

Zusammenfassung

Warum ist Umleitung nützlich?

  • Ausgaben speichern: Die Ergebnisse eines Befehls für eine spätere Überprüfung oder Verarbeitung aufbewahren.
  • Protokollieren: Fehlermeldungen für die Fehlersuche festhalten.
  • Automatisierung: Befehle aneinanderreihen und die Ausgabe des einen als Eingabe des anderen nutzen.
  • Filtern: Unerwünschte Ausgaben verwerfen.
  • Stapelverarbeitung: Daten aus Dateien verarbeiten, statt sie manuell einzutippen.
  • Skripte schreiben: Umleitungen sind unverzichtbar, um robuste Shell-Skripte zu schreiben.

Shell-Umleitungen geben dir fein abgestufte Kontrolle darüber, wie Programme mit Daten umgehen. So kannst du komplexe Workflows aufbauen und Informationen effektiv verwalten.

Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab