Die Auswahl an Programmier- und Skriptsprachen ist inzwischen riesig geworden. Zwischen modern(er)en Sprachen, wie Julia und Python, ist die Shellsprache bash bis heute weit benutzt. Die Konstrukte und Strukturen wirken inzwischen oft veraltet. Warum hält sich also bash immer noch?
Der große Vorteil ist wohl die Einfachheit in der Alltagsnutzung.
Die Unix-Betriebssysteme sind zusammen mit dieser Art von Skriptsprachen entstanden und gewachsen.
Der Umgang mit Dateien und Strukturen des Betriebssystems ist besonders gut optimiert.
Als Beispiel: nehmen wir an, wir wollen eine Aktion an allen Dateien eines Ordners vornehmen.
Nutzen wir dazu das interne if
-Konstrukt, könnte das so aussehen.
for i in $(ls); do
... Logik an $i ...
done
Der Befehl ls
gibt hier die Inhalte des aktuellen Ordners aus.
Durch das Konstrukt $( )
wird die Ausgabe in einen String umgewandelt.
Die einzelnen Einträge werden dann in der Variable $i
gespeichert und können dann benutzt werden.
Wollen wir an die Namen zum Beispiel bck
anhängen, um sie als veraltet zu markieren, können wir folgende Logik nutzen.
for i in $(ls); do
mv $i bck_$i
done
Widmen wir uns zunächst der Verwendung von Strings und Integern in Variablen.
mia@surface-mia:~$ i="Hallo Welt!"
mia@surface-mia:~$ echo $i
Hallo Welt!
Das Beispiel zeigt ein einfaches “Hallo Welt” Programm. Es kann entweder direkt in die Shell eingegeben, oder in einem kurzen Skript abgespeichert werden.
mia@surface-mia:~$ cat hallo_welt.sh
i="Hallo Welt!"
echo $i
mia@surface-mia:~$ bash hallo_welt.sh
Hallo Welt!
Die übliche Dateiendung für Skripte ist .sh
.
In dieser Form müssen Skripte immer mit dem Programm bash aufgerufen werden, das dann die Befehle interpretiert.
Wir können diese Information jedoch auch in das Skript schreiben.
Dazu ergänzen wir am Anfang die sogenannte Shebang-Zeile.
#!/usr/bin/bash
Die Zeichen #!
signalisieren dem Betriebssystem, dass nun der Pfad zum Programm, mit dem das Skript geöffnet werden soll, folgt.
Hier ist der Pfad zum ausführbaren Datei bash /usr/bin/bash
.
Der Befehl which
gibt die Pfade aller installierten Programme aus.
mia@surface-mia:~$ which bash
/usr/bin/bash
Wollen wir nun unser Skript ausführen, so bekommen wir folgende Ausgabe.
mia@surface-mia:~$ ./hallo_welt.sh
bash: ./hallo_welt.sh: Keine Berechtigung
Zur Sicherheit dürfen Dateien auf Unix-Betriebssystemen ohne weiteres nicht ausgeführt werden.
Dazu werden allen Dateien eine Reihe von Berechtigungen zugewiesen.
Diese können mit dem Befehl ls -l
eingesehen werden.
mia@surface-mia:~/Test$ ls -lh
insgesamt 8,0K
-rw-r--r-- 1 mia mia 24 29. Nov 13:46 hallo_welt.sh
drwxr-xr-x 2 mia mia 4,0K 29. Nov 13:58 Ordner
Wir erhalten ein Auflistung aller Inhalte im akutellen Verzeichnis. Ganz links werden die Rechte aufgelistet.
- || r w x || r w x || r w x
Die erste Stelle kennzeichnet den Datentypen. Unser Skript - eine Textdatei - erhält dabei das Zeichen -
, während ein Ordner durch d
gekennzeichnet ist.
Es folgen drei Zeichen, die die Rechte des Besitzers darstellen.
Jede Datei wird von einem Benutzer angelegt, der die Datei dann besitzt.
Dieser Nutzer soll meist die Berechtigung haben Dateien zu lesen und zu ändern, während andere Nutzer des selben Systems die Dateien nur lesen, oder gar nicht sehen sollen.
Das erste Zeichen kennzeichnet die Leseberechtigung ('r'
für read), also darf diese Datei betrachtet werden.
Das zweite Zeichen zeigt die Schreibberechtigung an ('w'
für write), darf diese Datei geändert werden.
Das dritte Zeichen kodiert die Ausführberechtigung ('x'
für eXecute), darf die Datei gestartet werden.
Bei diesen Berechtigungen werden nun drei Gruppen unterschieden. 1. Der Besitzer (“owner”) 2. Die Gruppe (“group”) 3. Alle Anderen Nutzer (“others”) Auf Nutzergruppen soll hier aber nicht weiter eingegangen werden.
Für uns interessant ist natürlich die Ausführberechtigung.
Zum Verändern der Rechte, können wir das Programm chmod
nutzen.
Wir wollen das Ausführen erlauben, also die eXecute Berechtigung - gekennzeichnet durch ein 'x'
- hinzufügen.
Der Befehl dazu ist einfach chmod +x
.
Das ganze wollen wir auf eine bestimmte Datei anwenden, damit ergibt sich insgesamt:
chmod +x hallo_welt.sh
Versuchen wir jetzt erneut unser Skript auszuführen, bekommen wir den erwarteten Output.
mia@surface-mia:~/Test$ ./hallo_welt.sh
Hallo Welt!
Damit haben wir unser erstes Bashskript geschrieben.
Beschäftigen wir uns nun mit den Steuerungskonstruktuen in bash.
Analog zu anderen Skriptsprachen, haben wir die üblichen Tools, wie if
und for
Blöcke zur Verfügung.
Die Syntax kann etwas umständlich wirken, erlaubt aber auch einige nützliche Anwendungen.
Schauen wir uns nochmal den Code aus der Einführung an.
for i in $(ls); do
mv $i bck_$i
done
Die Struktur eines range-for Konstrukts in bash sieht immer folgendermaßen aus.
for [Variable] in [Liste]
do
... Logik ...
done
Zwei Befehle können dabei durch ein ;
in eine Zeile geschrieben werden.
Wir haben auch bereits angesprochen, dass innerhalb eines $(...)
Aufrufs verschiedene Befehle ausgeführt und die Ausgabe in einen durch Leerzeichen getrennten String umgewandelt werden kann.
Dabei werden auch Zeilenumbrüche in Leerzeichen umgewandelt.
Führen wir im home
-Verzeichnis zum Beispiel den ls
Befehl aus und weisen die Ausgabe einer Variable test zu
test=$(ls)
bekommen wir als Ausgabe der Variable (echo $test
) zum Beispiel den folgenden String.
Bilder Dokumente Downloads go Musik Schreibtisch
Test Videos Vorlagen
Bei der Zuweisung der Einträge in der range-for Schleife, werden dabei durch Leerzeichen getrennte Zeichenketten als Einträge betrachtet. Die Regel keine Leerzeichen in Datei-, Ordner- und Programmnamen zu nutzen, ist im Zusammenhang mit Skripten also besonders wichtig.
Eine zweite Regel wird hier auch ersichtlich. Variablen müssen immer mit einem $
-Zeichen gekennzeichnet sein, außer bei einer Zuweisung.
Im Code der for-Schleife weisen wir der Laufvariable i
durch den Befehl i in $(ls)
die Einträge zu.
Wollen wir diese Einträge in der Schleife nutzen, so tun wir dies mit $i
.
Auch bei der direkten Zuweisung test=$(ls)
müssen wir die Variable in echo $test
mit dem $
-Zeichen kenntlich machen.
Ein weiterer häufiger Fehler bei Zuweisungen ist das Setzen von Leerzeichen.
Bei Variablenzuweisung dürfen keine Leerzeichen zwischen dem =
und den Namen stehen.
Der Aufruf test = $(ls)
wäre also ungültig.
Beschäftigen wir uns jetzt mit den if
-Konstrukten.
Die grundlegende Form einer Abfrage sieht wie folgt aus.
if
then
... Logik ...
elif
then
... Logik ...
else
... Logik ...
fi
Bei der Syntax gilt es also auf die then
und das abschließende fi
statement zu achten.
Die Bedingungen müssen in eckigen Klammern geschrieben sein.