claim.gif
Linux Magazin Linux User Easy Linux Ubuntu User International Linux Community
Erschienen in EasyLinux 06/2005   »   Ausgabe bestellen

Nützliche Funktionen für die Shell

Schnitzeljagd

von Elisabeth Bauer


Im Automatisieren von Routineaufgaben ist die Linux-Shell Spitze. Wir erklären, wie Sie sich mit maßgeschneiderten Funktionen viel Tippaufwand ersparen.

Wer manchmal mit der Linux-Kommandozeile arbeite, kennt das Problem: Viele Befehle sind so schwer zu merken und haben derart viele Aufrufparameter, dass man immer erst in die Manpage des Kommandos schauen muss, um eine einfache Aufgabe zu erledigen. Ein weiteres Ärgernis ist die Tipparbeit. Gerade Befehle mit vielen Parametern kosten bei der Eingabe viel Zeit. Um sich die Arbeit zu erleichtern, besteht die Möglichkeit, Shell-Funktionen zu verwenden. Wer häufig immer dieselben Kommandos eintippt, spart sich damit eine Menge Arbeit. Mit einem Aufruf führt die Shell dann gleich eine ganze Reihe von Befehlen aus, ohne dass Sie sie einzeln eingeben müssen.

Der Aufbau einer Funktion schaut so aus:

funktionsname() {
        ein_Befehl
        noch_einer
}

Am Anfang steht der Name, mit dem Sie die Funktion später aufrufen, gefolgt von runden Klammern. Die erste geschweifte Klammer ist das Signal für die Shell, dass nun alle Befehle folgen, die die Funktion zusammenfassen soll. Diese Kommandos schreiben Sie jeweils in eine Zeile. Sie sind dabei nicht auf zwei wie im obigen Beispiel beschränkt, sondern können Ihre Funktion beliebig viele Befehle abarbeiten lassen. Am besten veranschaulicht ein praktisches Beispiel, wie eine solche Shell-Funktion arbeitet.

Ihre Heimat haben Funktionen in der Datei .bashrc, die unter Linux versteckt im Home-Verzeichnis eines Benutzers liegt. Diese Datei können Sie mit jedem beliebigen Text-Editor bearbeiten und an Ihre Bedürfnisse anpassen. Hier verwenden wir als Beispiel den KDE-Text-Editor KWrite, da dieser im Gegensatz zu den Shell-Klassikern vi und emacs als grafisches Programm auch für Anfänger leicht zu bedienen ist.

Eine erste einfache Beispielfunktion erstellen Sie im Handumdrehen: Starten Sie aus einem Terminal-Fenster den Text-Editor KWrite und weisen Sie ihn an, die Datei .bashrc zu öffnen:

kwrite ~/.bashrc &

Die Tilde ist dabei eine Abkürzung, die die Shell automatisch durch den Pfad zu Ihrem Home-Verzeichnis ersetzt, also etwa durch /home/eli. Das & am Ende der Befehlszeile sorgt dafür, dass die Shell Ihnen nach dem Start von KWrite wieder einen so genannten Prompt zurückgibt, so dass Sie weitere Befehle eingeben können. Wenn Sie das Zeichen weglassen, ist die Shell solange blockiert, bis Sie kwrite beenden. Möchten Sie die .bashrc aus einem schon gestarteten KWrite heraus über den Dateidialog öffnen, drücken Sie im Auswahlfenster [F8]. Daraufhin zeigt der Text-Editor auch die versteckten, mit einem Punkt beginnenden Konfigurationsdateien in der Liste an (Abbildung 1).

Bei einigen Distributionen stehen in der .bashrc schon verschiedene Befehle. Diese können Sie getrost ignorieren und wie in Abbildung 2 Ihre erste Funktion darunter setzen:

mein-test() {
  echo "Hallo, dein aktuelles Verzeichnis ist"
  pwd
  echo "und dort liegen:"
  ls
}

Abb. 1: Nach einem Druck auf [F8] zeigt der Dateiauswahldialog von KWrite auch Dateien und Ordner an, deren Name mit einem Punkt beginnt.

Abb. 2: In der Datei ".bashrc" ergänzen Sie praktische Funktionen, die die Arbeit in der Shell erleichtern.

Speichern Sie die Datei und wechseln Sie zurück ins Terminal. Die Shell weiß noch nichts von der Änderung, deshalb weisen Sie sie mit

. ~/.bashrc

an, die Datei neu zu lesen. Der Punkt ist eine Abkürzung für das Kommando source, das Sie in manchen Handbüchern finden. Beim nächsten Login oder wenn Sie eine neue Shell aufmachen, ist dieser Aufruf nicht mehr nötig. Mit

mein-test

rufen Sie die neue Funktion auf. Die Shell führt nun die vier Kommandos aus, die zwischen den geschweiften Klammern stehen: echo gibt den Text in Anführungszeichen, pwd (print working directory) das aktuelle Verzeichnis und ls eine Liste der darin enthaltenen Dateien und Ordner aus (Abbildung 3).

Abb. 3: Die Shell-Funktion "mein-test" gibt den Namen des aktuellen Verzeichnis aus und listet seinen Inhalt auf.

Programmstart einmal anders

Auf diese Art fassen Sie beliebige Kommandos zusammen. Ein praktischer Anwendungsfall ist zum Beispiel das Starten mehrerer Programme in einem Rutsch. Wer die KDE-Sitzungsverwaltung nutzt, hat sich bestimmt schon einmal darüber geärgert: Wenn Sie KDE beenden, speichert die Desktop-Umgebung, welche Anwendungen gerade laufen, und startet sie beim nächsten Anmelden erneut. Dieses Verhalten ist jedoch lästig, wenn Sie sich nur anmelden, um schnell etwas am Rechner zu erledigen und dann warten müssen, bis die Sitzungsverwaltung das Starten der Anwendungen beendet hat.

Haben Sie deshalb die Sitzungsverwaltung im KDE-Kontrollzentrum unter KDE-Komponenten / Sitzungsverwaltung deaktiviert (Abbildung 4), können Sie ersatzweise eine Shell-Funktion nutzen, die alle benötigten Anwendungen mit nur einem einzigen Befehl startet. Die folgende Funktion ruft zum Beispiel die Programme KMail, Gimp und den MP3-Player XMMS auf:

start() {
  kmail &
  gimp &
  xmms &
}

Abb. 4: In diesem Dialog deaktivieren Sie die KDE-Sitzungsverwaltung, die automatisch alle beim letzten Abmelden laufenden Programme startet.

Speichern Sie die .bashrc, lesen Sie sie mit . ~/.bashrc im Konsolen-Fenster neu ein und rufen Sie die neue Funktion mit der Eingabe von start auf. Daraufhin arbeitet die Shell alle Befehle zwischen den geschweiften Klammern ab, startet also die drei dort eingestellten Programme.

Zusätzlichen Komfort erhalten Sie, indem Sie die Funktion ein wenig modifizieren:

start() {
  pushd
  kmail &
  cd $HOME/bilder
  gimp &
  cd $HOME/musik
  xmms &
  popd
}

Das Kommando pushd merkt sich das Verzeichnis, in dem Sie sich gerade befinden. popd am Ende der Funktion ist das passende Gegenstück und springt wieder in den mit pushd gespeicherten Ordner zurück. Vor dem Start von Gimp wechselt die Shell in das Verzeichnis bilder (cd $HOME/bilder) in Ihrem Home-Verzeichnis und anschließend nach musik (cd $HOME/musik). Wenn Sie nun in Gimp oder XMMS eine Datei öffnen, bietet der Auswahldialog Ihnen sofort das passende Verzeichnis bilder bzw. musik an. In den beiden Kommandos zum Verzeichniswechsel steht $HOME für das Home-Verzeichnis Ihres Benutzers. Bei $HOME handelt es sich um eine so genannte Variable, was Sie an dem vorangestellten Dollarzeichen erkennen.

Mit diesem Wissen sparen Sie eine Menge Tipparbeit ein. Denkbar sind zum Beispiel Startfunktionen für Programmgruppen, die Sie häufig zur gleichen Zeit verwenden: Eine Funktion start_net, die Browser, E-Mail- und Chat-Client startet, und eine Funktion start_work, die Textverarbeitung, Tabellenkalkulation und weitere Anwendungen für eher unangenehme Routineaufgaben zusammenfasst.

Den Fehlerteufel austreiben

Wichtig beim Shell-Programmieren -- nichts anderes machen Sie hier -- ist es, auf Kleinigkeiten zu achten. Wenn eine Funktion nicht das tut, was Sie erwarten oder nur eine Fehlermeldung ausgibt, schauen Sie sich die Zeilen noch einmal genau an: Sitzen alle Leerzeichen an der richtigen Stelle? Sind alle Befehle korrekt geschrieben? Geben Sie die Befehle normal in der Shell ein, um sie zu testen. Wenn Sie den Fehler partout nicht finden, hilft der Echo-Trick: Die Shell arbeitet die Befehle einer Funktion Zeile für Zeile ab. Stößt sie dabei auf einen Fehler, gibt sie meistens eine Fehlermeldung aus. Manchmal bleibt sie aber auch einfach hängen -- zum Beispiel, weil der Befehl weitere Eingaben erwartet -- und gibt gar nichts mehr aus. Um den Schuldigen zu identifizieren, setzen Sie nach jeden Befehl einen Aufruf von echo, in dem Sie angeben, welcher Befehl gerade ausgeführt wurde.

Im Beispiel der Funktion start würden Sie etwa

echo "kmail gestartet"

hinter den KMail-Aufruf setzen usw. und könnten genau verfolgen, welche Befehle die Shell schon ausgeführt hat und in welcher Zeile sie stolpert.

Mit Argumenten

Bisher haben Sie nur Befehle verwendet, die keine zusätzlichen Angaben wie einen Verzeichnis- oder Dateinamen erwarten, oder Sie haben diese fest in die Funktion eingebaut, wie im Beispiel der Verzeichniswechsel mit cd. Die Möglichkeiten von Shell-Funktionen sind damit jedoch nicht ausgereizt: Das nächste Beispiel knöpft sich das Kommando tar vor [1]. tar packt Verzeichnisse und Dateien -- auf Wunsch komprimiert -- in eine Archivdatei und eignet sich so wunderbar dazu, Backups anzufertigen oder einen Stapel Dateien bequem zu verschicken. Die Aufrufparameter von tar sind leider weniger hübsch -- zum Aus- und Entpacken müssen Sie sich gleich vier Optionen merken:

tar czvf datei.tar.gz verzeichnis

packt verzeichnis in ein gzip-komprimiertes Archiv namens datei.tar.gz. c steht für create (Erzeugen), z sorgt für die Kompression mit gzip, v (verbose) weist tar an, alle Dateinamen auszugeben, und f bestimmt, dass tar ein Dateiarchiv anlegen soll, statt zum Beispiel die Daten auf ein Bandlaufwerk zu schreiben (wozu das Kommando früher hauptsächlich diente). Auch zum Auspacken sind Sie wieder mit vier Buchstaben dabei:

tar xzvf datei.tar.gz

entpackt das Archiv im aktuellen Verzeichnis. Mit der folgenden Funktion ersparen Sie sich die Tipparbeit beim Einpacken:

pack() {
    tar czvf "$1-$(date +%y%m%d-%H%M%S).tar.gz" "$1"
}

Das sieht auf den ersten Blick reichlich kompliziert aus. Sie rufen die Funktion mit dem Verzeichnis auf, das Sie einpacken wollen, zum Beispiel:

pack photoalbum

In der Funktion finden Sie zweimal die Variable $1. Dort setzt die Shell automatisch das Argument ein, mit dem Sie die Funktion aufrufen. So führt sie in diesem Fall den Befehl

tar czvf "photoalbum-$(date +%y%m%d-%H%M%S).tar.gz" photoalbum

aus. Mit $(date +%y%m%d-%H%M%S) sorgen Sie dafür, dass das aktuelle Datum und die Uhrzeit Bestandteil des Archivnamens werden. Damit erhalten Sie auf bequeme Art ein Archiv mit Datumsstempel. Es erweist sich vor allem dann als praktisch, wenn Sie einen Ordner regelmäßig als Tar-Datei sichern.

Das Tar-Beispiel zeigt recht gut einen Hauptnutzen von Funktionen: Sie kürzen damit häufig gebrauchte Kommandos ab, bei denen Sie sich sonst schnell die Finger wundtippen oder deren Optionen Sie sich beim besten Willen nicht merken können. Gegenüber dem Befehl alias [2] haben Sie den Vorteil, dass Sie einer Funktion, wie bei tar gezeigt, Parameter übergeben können.

Download-Manager im Eigenbau

Damit lässt sich auch ein ganz auf die eigenen Bedürfnisse zurecht geschneiderter Download-Manager basteln. Wer etwa von einer Website nur die Bilder, Video- und Sound-Dateien herunterladen möchte, nicht aber Texte und die HTML-Seiten, erledigt das in der Shell normalerweise mit folgendem Bandwurm-Kommando:

wget -r -H -l1 -A jpg,gif,png,avi,mpg,mp3 www.adresse.de

Das Programm wget [3] zieht hier rekursiv (-r) alle Dateien vom Typ JPG, GIF, PNG, AVI, MPG oder MP3 von der Website www.adresse.de -- und zwar genau eine Ebene tief (-l1 für "Level 1"), d. h. er folgt den Links auf der angegebenen Adresse, aber nicht weiteren. -H sorgt dafür, dass wget auch Links zu anderen Servern folgt. Mit einer Shell-Funktion sparen Sie sich die Tipperei:

down() {
  wget -r -H -l"$1" -A jpg,gif,png,avi,mpg,mp3 "$2"
}

Rufen Sie nun down 2 www.easylinux.de auf, erhalten Sie alle Dateien dieser Typen von der EasyLinux-Website. Wie man aus der Nummerierung erwarten kann, kennt die Shell nicht nur $1, sondern verpackt auch alle weiteren Argumente in nummerierte Variablen. Ein Leerzeichen trennt dabei jeweils eins vom anderen.

Optimal ist diese Funktion jedoch noch nicht. Was, wenn Sie statt einer URL mehrere angeben wollen? Direkt in der Shell aufgerufen, erledigt wget das ohne Murren, doch die Funktion liefert beim Versuch mit mehreren Adressen nur einen Fehler zurück. Theoretisch könnten Sie hinter "$2" noch "$3" und "$4" setzen, aber besonders elegant ist das nicht. Doch mit dem Befehl shift und der speziellen Variable $@ lösen Sie dieses Problem:

down() {
  level="$1"
  shift
  wget -r -H -l"$level" -A jpg,gif,png,avi,mpg,mp3 "$@"
}

Hier verpacken Sie zuerst den Inhalt von $1 -- die Download-Tiefe -- in eine neue Variable namens level. shift schiebt dann alle übergebenen Parameter eins weiter nach links, aus $2 wird $1, aus $3 wird $2 usw. $@ schließlich enthält standardmäßig alle Parameter und übergibt sie gesammelt an den wget-Befehl. Damit ist der kleine Download-Manager fertig, Dateiendungen können Sie dort nach Gusto ergänzen (amü).

Infos
[1] Artikel über Packprogramme auf der Kommandozeile: Heike Jurzik, "Komprimierungskünstler", EasyLinux 07/2004 S. 84f. http://www.easylinux.de/Artikel/ausgabe/2004/07/084-guru-tar
[2] Alias-Artikel: Elisabeth Bauer, "Schleichwege", EasyLinux 07/2004 S. 82f.
[3] wget-Artikel: Heike Jurzik, "Spieglein, Spieglein an der Wand...", EasyLinux 04/2004 S. 78ff.

Dieser Online-Artikel kann Links enthalten, die auf nicht mehr vorhandene Seiten verweisen. Wir ändern solche "broken links" nur in wenigen Ausnahmefällen. Der Online-Artikel soll möglichst unverändert der gedruckten Fassung entsprechen.

Druckerfreundliche Version | Feedback zu dieser Seite | Datenschutz | © 2017 COMPUTEC MEDIA GmbH | Last modified: 2007-04-05 11:10

Nutzungsbasierte Onlinewerbung

[Linux-Magazin] [LinuxUser] [Linux-Community] [Admin-Magazin] [Ubuntu User] [Smart Developer] [Linux Events] [Linux Magazine] [Ubuntu User] [Admin Magazine] [Smart Developer] [Linux Magazine Poland] [Linux Community Poland] [Linux Magazine Brasil] [Linux Magazine Spain] [Linux Technical Review]