Ein- und Ausgabeverarbeitung
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 Befehlsumlenkung. stdin wird bis zu einer zuvor bestimmten Markierung gelesen.
$ cat << EOF-EOF Hallo Welt EOF-EOF
Das folgende Skript beinhaltet Programm und Daten. grep liest dabei stdin bis zur Zeile 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