Die Bash besitzt eine Reihe von Funktionen die den Gebrauch der Shell vereinfachen und beschleunigen sollen. Hierzu zählt z. B. die Kommando- und Pfadvervollständigung und die History.
Stellen Sie sich vor, Sie haben ellenlange Befehle in die Shell eingetippt und möchten nun ein Kommando noch mal wiederholen und sei es auch in etwas abgewandelter Form. Jetzt den ganzen Rattenschwanz noch mal eintippen? Nein, Danke. Für diesen Zweck gibt es die History. Drücken sie auf die Pfeil nach oben Taste Ihrer Tastatur und schon erscheint der zuletzt eingegebene Befehl erneut. Sie können diesen dann auch noch mal abwandeln und ihn dann erst durch drücken auf Return abschicken. Möchten Sie nicht den letzten sondern den vorletzten oder vor-vorletzten Befehl wieder haben, drücken Sie die Pfeil-nach-oben-Taste mehrfach.
Sie tippen einen längeren Befehl ein. Praktisch wäre es jetzt, wenn der Befehl quasi sich selbst zu Ende schreiben würde. Auch das gibt es. Drücken sie auf die Tab-Taste und der Befehl versucht sich selbst zu vervollständigen. Dies kann natürlich nur so weit funktionieren, wie es keine Doppeldeutigkeiten gibt. Falls Doppeldeutigkeiten auftreten wird der Befehl nur so weit vervollständigt, wie es eindeutig ist und dann gibt die Shell einen Ton von sich. Tippen sie nun einen weiteren Buchstaben ein und dann nochmal auf die Tab-Taste und der Befehl wird weiter vervollständigt. Das gleiche funktioniert auch mit Pfaden. In meinem Home-Verzeichnis existiert z. B. ein Ordner namens Download. Wenn ich in diesen Wechseln will, kann ich den Ordnernamen automatisch vervollständigen lassen:
rene@thor:~> cd Dow
jetzt auf die Tabtaste drücken und es wird ergänzt:
rene@thor:~> cd Download/
Nur mit cd Do wäre es noch nicht gegangen, da es in meinem Homeverzeichnis auch einen Ordner Documents gibt.
Als Wildcards werden Zeichen bezeichnet, die als Platzhalter für andere Zeichen stehen können. Die Bash kennt viele Wildcards. Die beiden einfachsten und wichtigsten sind "?" und "*". Das ? steht dabei für genau ein beliebiges Zeichen, während der * für beliebig viele Zeichen steht. Wie lassen sich Wildcards anwenden? Nehmen wir an, Sie möchten sich in einem Verzeichnis in dem sehr viele Bilder in unterschiedlichen Formaten enthalten sind, nur die GIF-Bilder auflisten lassen. Der Befehl um ein Verzeichnisinhalt anzuzeigen ist ls
. Da wir die Anzeige einschränken wollen, geben wir ein:
rene@thor:~> ls *.gif
und schon bekommen wir das gewünschte Ergebnis.
Was nun aber,wenn es in dem Verzeichnis sowohl Dateien mit der Endung .gif, als auch .GIF gibt? Achtung Stolperfalle! Unter Linux wird streng zwischen Groß- und Kleinschreibung unterschieden. Aber auch hierfür gibt es Möglichkeiten: Wird ein Ausdruck in geschweifte Klammern eingeschlossen, kann man auch noch Alternativen angeben:
rene@thor:~> ls *.{gif,GIF}
Nun werden beide Möglichkeiten berücksichtigt. Das Komma dient innerhalb der geschweiften Klammer als Trenner für die jeweiligen Alternativen.
Bei manchen Kommandos sind darüber hinaus noch weitere Möglichkeiten gegeben, wie z. B sogenannte reguläre Ausdrücke. Reguläre Ausdrücke sind sehr mächtige Funktionen um Text zu suchen oder zu ersetzen und können z. B bei Befehlen wie grep (sucht Text) oder sed (verändert Zeichen in einem Stream) verwendet werden. Da jedoch reguläre Ausdrücke ein Fortgeschrittenenthema sind möchte ich im Rahmen dieser kleinen Erläuterung nicht näher darauf eingehen.
Eine in manchen Fällen ebenfalls sehr praktische Sache ist die sogenannte Ausgabeumleitung. Durch die Ausgabeumleitung kann die Ausgabe eines Befehls statt auf dem Bildschirm in eine Textdatei umgeleitet werden. Die Ausgabeumleitung wird durch das Zeichen ">" gesetzt. Wenn ich beispielsweise ein Verzeichnislisting statt auf dem Bildschirm ausgegeben haben will, in eine Datei schreiben möchte, um diese später weiterverwenden zu können kann ich schreiben:
rene@thor:~> ls > datei.txt
Schon findet sich das Verzeichnislisting in der Datei "datei.txt" wieder. Möchte ich hingegen etwas an eine Datei unten anfügen, ohne das der vorige Inhalt der Datei gelöscht wird nutze ich ">>". Das Zeichen ">" legt eine neue Datei an, wenn noch keine Datei dieses Namens vorhanden war, bzw. überschreibt eine vorhandene Datei. Das Zeichen ">>" legt ebenfalls eine neue Datei an, wenn noch keine Datei dieses Namens vorhanden ist, aber überschreibt nichts, wenn bereits eine Datei vorhanden ist. Der Inhalt wird am Dateiende einfach hinzugefügt. Für beide Varianten gilt außerdem: Sollte die Datei noch nicht vorhanden sein, wird sie selbst dann angelegt, wenn der Befehl gar keine Ausgabe erzeugt. Sie bleibt in diesem Fall eben einfach leer.
Falls sie mal eine Ausgabeumlenkung in eine Datei machen und der Befehl gibt Ihnen eine Fehlermeldung zurück, werden Sie feststellen, daß diese nicht in der Datei landet, sondern auf dem Bildschirm ausgegeben wird. Dies liegt daran, das Linux 2 verschiedene Ausgabekanäle für normale Ausgaben und für Fehler kennt. Die Kanäle haben Nummern. Die Standardausgabe hat die Nummer 1 und die Standardfehlerausgabe die Nummer 2. Wird bei einer Ausgabeumlenkung keine Kanalnummer angegeben, bezieht sich diese immer auf die Standardausgabe. Es kann aber auch explizit eine Kanalnummer angegeben werden. Die Kanalnummer wird unmittelbar vor das >-Zeichen gesetzt (ohne Leerschritt). Z. B.:
rene@thor:~> ls 2> datei.log
Sinnvoll kann so eine Umleitung aller Fehler in eine Datei z. B. zum Anlegen von Logdateien sein. Führt man z. B. ein Script als Cronjob aus, kann man alle Fehlermeldungen in eine Logdatei schreiben, die man von Zeit zu Zeit auswertet, ob alles glatt läuft. Cronjobs sind übrigens zeitgesteuerte Befehle oder Scripts, die beispielsweise jeden Tag um eine bestimmte Uhrzeit gestartet werden und im Hintergrund laufen.
Wie man sich nun fast denken kann, gibt es wenn es eine Ausgabeumleitung gibt, auch eine Eingabeumleitung. Diese funktioniert mit dem "<"-Zeichen. Für die Eingabeumleitung gibt es allerdings wesentlich weniger Anwendungsfälle als für die Ausgabeumleitung.
Pipes sind ebenfalls eine Form der Ausgabeumleitung. Jedoch ist eine Pipe nicht auf die Umleitung in eine Datei festgelegt. Mit Pipes kann man mehrere Befehle miteinander verknüpfen. Der jeweils nächste Befehl nimmt die Ausgabe des vorherigen Befehls als Eingabe entgegen. Das Zeichen hierfür ist: |
. Pipes können ein sehr mächtiges Werkzeug sein. Ein Beispiel aus der Praxis: Ich möchte in der Liste aller installierten RPM-Pakete (das auf den meisten Linux-Distributionen verwendete Paketformat für Softwarepakete) eine bestimmte Software suchen um festzustellen ob diese installiert ist oder nicht. Nun weiß ich zwar den Namen des Programms, aber leider nicht die genaue Version. Der Befehl rpm
kann mir aber nur entweder alle installierten Pakete auflisten (was sehr viele sind) oder aber er verlangt die exakte Bezeichnung inklusive Versionsnummer. Der Befehl grep sucht einen beliebigen Textabschnitt aus einer Datei oder der Standardeingabe heraus und gibt die ganze Zeile in der der gesuchte Text steht wieder. Mit einer Pipe verknüpfen wir beide Befehle:
rene@thor:~> rpm -qa | grep mozilla mozilla-1.4-72 mozilla-devel-1.4-72 mozilla-deat-1.4-56
rpm -qa
listet normal alle installierten Pakete auf. Pro Paket in einer Zeile. Da wir diese Liste durch grep filtern bekommen wir nur das gewünschte Ergebnis. Auf einem Debian-basierten System können Sie übrigens den Befehl rpm
nicht verwenden, da Debian ein anderes Paketformat verwendet.
Was aber nun wenn wir die Ausgabe eines Befehls sowohl in eine Datei schreiben wollen, als auch auf dem Bildschirm ausgeben wollen? Hierfür gibt es den Befehl tee
. Dieser kann ebenfalls in einer Pipe verwendet werden:
rene@thor:~> ls | tee test.txt
Nun wird der aktuelle Verzeichnisinhalt sowohl in die Datei test.txt gespeichert, als auch auf dem Bildschirm ausgegeben. Sollten Sie eine Fehlermeldung erhalten, ist vermutlich bei Ihnen das Programm tee
nicht installiert. Es sollte bei jeder Distribution dabei sein. Sie können es einfach nachinstallieren.