Ein- und Ausgabeverarbeitung

Aus Mikiwiki
Wechseln zu: Navigation, Suche

Ein- und Ausgabeverarbeitung / EAV (engl. Input/Output / I/O)

Lese- und Schreiboperationen an Dateien werden auf Unix-Betriebssystemen über numerierte Kanäle (Dateideskriptoren) abgehandelt. Möchte ein Programm eine Datei öffnen, um daraus zu lesen, so erhält es eine Nummer, über die es mit der gewünschten Datei arbeiten kann. Die ersten drei Dateideskriptoren sind für Standardwerte reserviert.

Dateideskriptor Name Bedeutung Standardbelegung Zeichen
0 stdin Standardeingabe Tastatur <
1 stdout Standardausgabe Terminal / Bildschirm >
1>
2 stderr Standardfehlerausgabe Terminal / Bildschirm 2>

Anwendungen von "stdin" und "stdout" sind Befehlsweiterleitungen und Befehlsumleitungen.

Befehlsgruppierung

Durch die runden Klammern "()" oder die geschweiften Klammern "{}" lassen sich Befehle gruppieren.

In einer Subshell wird der zuerst der erste Befehl ("cd /tmp"), danach der zweite ("ls") ausgeführt. Nach Abarbeitung beider Befehle befindet man sich also immer noch im ursprünglichen Verzeichnis.

$ (cd /tmp; ls)

Zusätzlich wird das Ergebnis in die Datei "outfile" im aktuellen Verzeichnis geschrieben.

$ (cd /tmp; ls) > outfile

In der aktuellen Shell wird zuerst der erste Befehl ("cd /tmp"), danach der zweite ("ls") ausgeführt. Nach Abarbeitung des ersten Befehls befindet man sich im Verzeichnis "/tmp" und bleibt auch dort. Zu beachten ist auch der Strichpunkt nach dem zweiten Befehl.

$ { cd /tmp; ls; }

Befehlstrenner

Neben "Carriage return" sind auch die Zeichen ";" und "&" sogenannte Befehlstrenner (engl. command separator).

Zuerst wird der erste Befehl ("date") ausgeführt, danach unabhängig vom ersten der zweite ("who").

$ date; who

Der erste Befehl ("du -s /") wird im Hintergrund ausgeführt, der zweite ("who") dagegen sofort.

$ du -s / & who

Befehlsverknüpfung

Anstatt mehrere Befehle einzeln abzusetzen, können diese Befehle durch Strichpunkte (";") getrennt auch auf einer Zeile geschrieben werden und werden direkt hintereinander ausgeführt.

$ mkdir directory2
$ cd directory2
$ cp ../directory1/* .

ist also gleichwertig mit

$ mkdir directory2; cd directory2; cp ../directory1/* .

Ebenso ist es möglich, einen zweiten Befehl nur dann auszuführen, wenn der vorangehende Befehl erfolgreich war. Beispielsweise prüft der Befehl test, ob die Datei "file" existiert und schreibbar ("-w") ist - falls dies zutrifft, wird sie durch den Befehl rm gelöscht.

$ test -w file && rm file

Beispielsweise kann mit dem Befehl test auch geprüft werden, ob das Verzeichnis ("-d") "directory" vorhanden ist. Nur falls das nicht zutrifft, wird es mit dem Befehl mkdir erstellt.

$ test -d directory || mkdir directory

Beim Installieren neuer Software aus den Quellen kann der übliche Dreierschritt aus "./configure", "make" und "make install" derart verbunden werden, dass jeder folgende Befehl nur dann weitermacht, wenn der vorangehende keine Fehler produziert hat.

# ./configure && make && make install

Befehlsweiterleitung

Bei der Weiterleitung eines Befehls wird die Standardausgabe ("stdout") des eines Befehls (anstatt an die Konsole) in den Eingabekanal ("stdin") des nächsten Befehls geschickt. So entsteht eine sogenannte "Leitung" (engl. pipe). In einer Befehlszeile können beliebig viele Befehle mit solchen "Leitungen" verknüpft werden - diese "Leitungen" sind der Hauptgrund für den Erfolg und die Beliebtheit der Shell.

Jeder Befehl der Befehlsweiterleitung wird dabei in einer eigenen Subshell als eine Art Unterprozess ausgeführt. Das geschieht für alle Befehle parallel - Daten gehen in einer Befehlsweiterleitung aber keine verloren, da langsamere Prozesse die schnelleren wenn nötig bremsen. Die Rückgabewerte sämtlicher Befehle der Befehlsweiterleitung werden in der Variable "PIPESTATUS" abgelegt.

Beispiel:

$ ls -al | grep abc
$ echo $PIPESTATUS
0

Anzeige einer Liste der Dateien im Verzeichnis "/usr/bin", wobei nur die Dateien angezeigte werden (keine Verzeichnisse), wobei eine umgekehrte numerische Sortierung am Ende des vierten Felds nach dem fünften Feld (Dateigrösse) stattfindet, wobei nur die erste Zeile (also diejenige mit der grössten Dateigrösse) ausgegeben wird, wobei nur das achte Feld (der Dateiname) angezeigt wird.

$ ls -l /usr/bin | grep ^- | sort -nr +4 -5 | head -1 | awk '{ print $8 }'

Finden aller Dateien mit Endung "jpg" und Einfärben dieser Endung in der Ergebnisliste.

$ find . -name "*jpg" | grep --color jpg
./back.jpg
./front.jpg

Umlenkung der Ausgabe mittels tee in mehrere Dateien sowie auf den Bildschirm.

Befehl | tee Datei Datei

Beispiel:

$ who | tee eingeloggt.txt | grep mik
$ tar cvf backup.tar * | tee backup.log

Befehlsausgabeumleitung

Umlenkung der Standardausgabe in eine Datei. Besteht bereits eine Datei mit diesem Namen, wird sie ohne Vorwarnung überschrieben. Dieses Verhalten lässt sich ab der Korn-Shell mit dem Befehl "set -o noclobber" ändern. Damit die Shell ungeachtet dieser Einstellung eine bestehende Datei gleichen Namens überschreibt, kann > | verwendet werden.

Befehl > Datei
bzw.
Befehl 1> Datei

Umlenkung aller vom betreffenden Dateideskriptor bezeichneten Kanal ankommenden Zeichen in eine Datei.

Befehl Dateideskriptor > Datei

Umleitung der Standardausgabe von Befehl ls in die Datei "index", während die Standardfehlerausgabe ins virtuelle Datennirwana "/dev/null" geschrieben wird.

$ ls > index 2> /dev/null

Umlenkung von der Standard- und der Standardfehlerausgabe in eine die Datei.

Befehl &> Datei

Umlenkung von der Standardausgabe in eine Datei. Besteht bereits eine Datei mit diesem Namen, so wird die Standardausgabe an diese Datei angehängt.

Befehl >> Datei

Umlenkung der Ausgaben eines Dateideskriptors auf einen anderen Dateideskriptor oder auf eine andere Datei.

Befehl Dateideskriptor >& Dateideskriptor oder Datei

Standard- und Standardfehlerausgabe des Befehls ls werden in dieselbe Datei umgeleitet.

$ ls > datei 2>&1
oder
$ ls > datei_stdout 2> datei_stderr 2>&1

Umleitung der Ausgabe "Fehler" in die Standardfehlerausgabe.

$ echo "Fehler" >&2

Umleitung der Standardfehlerausgabe des Befehls ls ins Datennirwana ("/dev/null") um und leitet gleichzeitig auch die Standardausgabe auf die Standardfehlerausgabe um. Im Fehlerfall wird also nichts am Bildschirm angezeigt.

$ ls -l /tmp 2> /dev/null >&2

Inhalt einer Datei an die Eingabe (stdin) eines Programms schicken.

Befehl Dateideskriptor < Datei

Beispiele:

$ cat < datei
$ mail -s "brief" mik < brieftext
Befehl Dateideskriptor <& Dateideskriptor oder Datei
ACKER=$(echo 'unload to ...;')
$ isql siasdb - <<EOF
${ACKER}
EOF

Umleitung der vollständigen Ausgabe oder eines Teils der Ausgabe eines Skripts in eine Datei.

#!/bin/bash

# ...Teil des Skripts ohne Ausgabeumleitung...

# code block
{
  # ...Teil des Skripts mit Ausgabeumleitung
} > ausgabe 2> fehler  # auch möglich: > ausgabe 2>&2

# ...weiterer Teil des Skripts ohne Ausgabeumleitung...

Here-Dokument

Das Here-Dokument ist ein Spezialfall der Befehlsumleitung. Es handelt sich um ein elegantes Mittel, um Konfigurationsdateien oder kurze Texte direkt in Skripte einzubetten. "stdin" wird dabei bis zur zuvor angegebenen Markierung eingelesen. Die Bash übernimmt den Text einschliesslich Zeilenumbrüchen und expandiert sogar Variablen.

"stdin" wird bis zur Markierung "EOF" gelesen.

$ cat << EOF
Hallo Welt
EOF

"stdin" wird bis zur Markierung "EOF" gelesen. Mit der Variante "<<-" darf die Eingabe zur besseren Lesbarkeit sogar eingerückt werden - die Bash entfernt die Zeichen später.

#!/bin/bash
for i in anna berta carola
  do
  cat <<- EOF | mail Einladung "${i}@beispiel.xx"
  Liebe ${i}

  Kommst Du zu meinem Geburtstag? Ich freue mich!

  XOX
EOF
  done

Das folgende Skript "telefon" beinhaltet Programm und Daten. grep liest dabei "stdin" bis zur Markierung "END".

$ cat > telefon
grep -i "$*" << END
Chef    102938
Karin   674839
Esther  123456
Schwester   987654
Buero   172839
END
CTRL+D
$ chmod +x telefon
$ ./telefon chef
Chef    102938

Weblinks

Herausgeber Sprache Webseitentitel Anmerkungen
country US.gif Wikipedia eng Input/Outputwbm Enzyklopädischer Artikel