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.

Datei-
deskriptor
Name Bedeutung Standardbelegung Zeichen
0 stdin Standardeingabe Tastatur <
1 stdout Standardausgabe Terminal / Bildschirm >
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

Befehlsumleitung

Umlenkung von stdout 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. Beispielsweise kann stdout in die Datei "index" geleitet werden, während die Fehlermeldungen aus stderr im virtuellen Datennirwana "/dev/null" verschwinden.

Befehl Dateideskriptor > Datei

Beispiel:

$ ls > index 2> /dev/null

Umlenkung von stdout und stderr in eine Datei.

Befehl &> Datei

Umlenkung von stdout in eine Datei. Besteht bereits eine Datei mit diesem Namen, wird stdout an diese Datei angehängt.

Befehl >> Datei

Umlenkung der Ausgaben eines Dateideskriptors auf einen anderen Dateideskriptor oder auf eine andere Datei. Beispielsweise können stdout und stderr in dieselbe Datei umgelenkt werden.

Befehl Dateideskriptor >& Dateideskriptor oder Datei

Beispiel:

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

Umleitung der Ausgabe "Fehler" nach stderr.

$ echo "Fehler" >&2

Leitet stderr des Befehls ls ins Datennirmwana ("/dev/null") um und leitet gleichzeitig auch stdout auf stderr aus. Es wird also auch im Fehlerfall 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

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