Auch Linux-Anwender haben die Wahl zwischen unzähligen Shells. Doch welche ist die richtige? Und wie einfach portieren Sie Skripte zwischen den Varianten?
Wer heutzutage eine Kommandozeile öffnet, sitzt mit hoher Wahrscheinlichkeit vor der Bourne Again Shell, kurz Bash [1]. Sie gehört offiziell zum GNU-Projekt und steht in der aktuellen Version 4.4 unter der GPLv3. Die Entwickler der Bash orientierten sich zunächst an der Bourne Shell, die Stephen R. Bourne Ende der 1970er-Jahre für Unix schrieb. Von dieser leitet sich der Name ab.
Im Lauf der Zeit erhielt die Bash zahlreiche weitere nützliche Funktionen und übernahm sogar einige Konzepte von der Korn Shell (Ksh) und der C-Shell (Csh) [2]. Standardmäßig kommt sie in allen großen Distribution zum Einsatz, darunter OpenSuse Leap, Fedora und Ubuntu und deren Derivaten. Unter Ubuntu lauert allerdings eine kleine Falle: Zwar ist die Bash standardmäßig aktiv, das Programm /bin/sh verweist jedoch auf die Dash [3]. Die verarbeitet zwar Skripte deutlich flotter, ist aber nicht vollständig zur Bash kompatibel.
Das wirkt sich vor allem dann aus, wenn Sie für die Bash geschriebene Skripte starten wollen, deren erste Zeile den Shebang #!/bin/sh enthält. Möchten Sie sichergehen, rufen Sie das Skript unter Ubuntu und Derivaten immer explizit mit bash script.sh auf, oder Sie passen die erste Zeile im Skript an.
Konkurrenz
Nur kurze Zeit nach der Bash betrat Anfang der 1990er-Jahre die Z-Shell erstmals die Bühne [4]. OpenSuse installiert das kurz Zsh genannte Programm standardmäßig; bei den meisten anderen großen Distributionen wie Ubuntu und Fedora ziehen Sie es über den Paketmanager nach.
Die Funktionen der Z-Shell orientieren sich an der Bash, sie ergänzt deren Umfang aber um weitere Elemente vor allem aus der Korn-Shell. Auf Wunsch verhält sich die Zsh wie die Bourne-, Korn- oder C-Shell (Emulator-Modus). Sie garantiert jedoch keine vollständige Kompatibilität, was insbesondere für die C-Shell gilt. Während die Z-Shell selbst unter einer BSD-Lizenz steht, unterliegen einige ihrer Komponenten der GPL.
Die jüngste Shell unter den drei Kandidaten hört auf den einprägsamen Namen Fish [5]. Die Friendly Interactive Shell erschien erstmals 2005 und schneidet zahlreiche alte Zöpfe ab. So bietet sie ausschließlich solche Kommandos an, die kein anderes Programm übernimmt.
Das hat unter anderem zur Folge, dass sie nicht in der Lage ist, einfache Rechenaufgaben zu erledigen. Die meisten großen Distributionen halten die Fish in ihren Repositories vor, installieren die unter der GPL v2 stehende Software aber nicht standardmäßig.
Obwohl sich alle drei Shells am Posix-Standard orientieren, folgt ihm offiziell nur die Bash [6]. Sie bringt sogar einen entsprechenden Modus mit, der sich noch strikter an die Spezifikation hält und etwa die Bash-eigenen Konfigurationsdateien ignoriert [7].
Bedienung!
Die Eingabe von Befehlen lehnt sich in allen drei Shells wahlweise an Emacs oder Vi an. Überall findet sich zudem ein Multiline-Modus im Angebot, der die Eingabe von Kommandos erlaubt, die sich über mehrere Zeilen erstrecken.
Die einzelnen Bestandteile eines Befehls färben Bash, Fish und Zsh auf Wunsch bunt ein, wobei sich das Schema individuell anpassen lässt. Fish erlaubt dabei sogar den Einsatz von bis zu 16,8 Millionen Farben. Selbst den Aufbau des Prompts dürfen Sie in allen drei Shells umgestalten.
In der Z-Shell führt jede Aktion am Prompt ein sogenanntes Widget aus. Per [Esc]+[B] rufen Sie etwa ein Widget auf, über das Sie den Cursor zum Anfang des Wortes versetzen. Sie dürfen eigene Widgets erstellen, wozu Sie lediglich eine passende Shell-Funktion zu schreiben brauchen.
Alle drei Shells merken sich jedes abgesetzte Kommando. Aus dieser History rufen Sie per Tastenkombination ältere Befehle ab. Die Zsh merkt sich standardmäßig nur die letzten 30 Zeilen und verwirft zudem beim Beenden die Liste. Dies ändern Sie bei Bedarf über eine entsprechende Konfiguration, in der Sie die Software anweisen, dass alle offenen Shells sich eine History teilen.
Auf Wunsch vervollständigen Bash, Fish und Zsh einen teilweise eingetippten Befehl. Diese sogenannte Auto-Completion vermag die Namen von Variablen, Benutzern, Hosts und Dateien zu komplettieren. In allen drei Shells besteht die Möglichkeit, diese Funktion mit eigenen Regeln zu ergänzen.
Bash und Zsh bieten zudem eine eingeschränkte Rechtschreibkorrektur, wobei die Z-Shell deutlich intelligenter agiert. Während etwa die Bash nur Dateinamen hinter cd verbessert, korrigiert die Zsh unter anderem auch falsch geschriebene Programmnamen. Fish hingegen schlägt schon beim Tippen einen möglichen Befehl aus der History vor und hebt (Tipp-)Fehler rot hervor (Abbildung 1).

Abbildung 1: Die Fish schlägt hier schon während der Eingabe das passende Verzeichnis Downloads vor.
Perlenschnur
Variablen dienen dazu, Daten aufzunehmen. In der Bash oder Zsh nutzen Sie diese, indem Sie etwa farbe=rot definieren. Unter Fish benötigen Sie dagegen explizit das Schlüsselwort set für diesen Zweck:
set farbe rot
Es fehlt außerdem das Gleichheitszeichen zwischen dem Namen und dem Wert, was die beiden Verfahren inkompatibel macht.
Sowohl die Bash und die Fish als auch die Zsh können mehrere Werte in sogenannten Arrays speichern. Je nach Variante heißen diese intern Listen, Felder oder Vektoren. Der Zugriff auf ein Element im Array erfolgt dabei durch die Angabe der Position:
farben[1]=rot
In der Bash sowie der Zsh beginnt dabei die Zählung bei 0. Im Beispiel würde das Wort rot daher an der zweiten Stelle des Arrays farben abgelegt. Fish hingegen startet bei 1, womit im obigen Beispiel das erste Element im Array rot wäre.
Zudem kennt Fish den Operator .., über den Sie auf mehrere Elemente gleichzeitig zugreifen:
echo $farben[2..4]
In diesem Beispiel würden die Farben an den Positionen 2, 3 und 4 des Arrays ausgegeben.
Austausch
Alle Shells beherrschen die Command Substitution, mit der Sie ein Kommando in ein anderes einbauen. Im folgenden Beispiel würden Bash und Zsh zunächst den Befehl date ausführen und den zurückgelieferten Wert dann als Parameter an das Kommando mkdir durchreichen:
mkdir $(date +"%Y-%m-%d")
In älterem Code findet sich dafür noch oft die mittlerweile als veraltet geltende Schreibweise mit Backticks `date +"%Y-%m-%d"`. Die Fish gestaltet den Code leserlicher. Sie versteht keine der beiden Varianten, sondern verlangt nach einfachen Klammern:
mkdir (date +"%Y-%m-%d")
Nach dem gleichen Prinzip integrieren die Shells den Inhalt von Variablen in Texte. In der Bash und der Zsh setzen Sie die Variable dazu in geschweifte Klammern:
ls brief${datum}.txt
Fish tanzt hier allerdings erneut mit einer etwas anderen Syntax aus der Reihe:
ls brief{$datum}.txt
Bash, Fish und Zsh bieten einige vordefinierte und spezielle Variablen, die sich allerdings von Shells zu Shell unterscheiden. So finden etwa Bash- und Zsh-Anwender in der Variablen $1 den ersten dem Skript auf der Kommandozeile mit auf den Weg gegebenen Parameter. Fish kennt hingegen keine Variable $1, dort extrahieren Sie bei Bedarf alle übergebenen Parameter aus dem Array $argv.
Geschlabber
Alle drei Shells erlauben in Dateinamen den Einsatz von verschiedenen Platzhaltern (Globbing oder Filename Expansion genannt). So steht bei allen drei Shells das Fragezeichen ? für einen beliebigen Buchstaben. Die Bash bietet darüber hinaus noch folgende Notation:
ls @(brief|readme).txt
Dieser Befehl listet nur die Dateien brief.txt und readme.txt auf (Abbildung 2). Die Zsh kann dasselbe, verlangt aber standardmäßig nur die Angabe der Klammern: ls (brief|readme).txt. Beide Shells erlauben auch komplexere Bedingungen innerhalb der Klammern.
Die Zsh bietet zudem noch sogenannte Glob Qualifiers, mit denen Sie ganz bestimmte Dateitypen aufspüren. So listet etwa ls *(-@) alle derzeit ins Leere führenden symbolischen Links auf.
Die Bash und Zsh vermögen zudem Zeichenketten zu manipulieren. So liefert etwa ${var:4:2} das fünfte und sechste Zeichen aus dem Text in der Variablen var zurück. Mit beiden lösen Sie außerdem einfache Rechenaufgaben (Abbildung 3). Um etwa 1 und 2 zu addieren, verwenden Sie das folgende Konstrukt:
summe=$((1+2))
Sowohl die Funktionen zum Rechnen wie auch jene zum Bearbeiten von Texten reichen jedoch in keiner Weise an die Fähigkeiten spezieller Programme wie Bc, Sed und Awk heran.

Abbildung 3: Sowohl mit der Bash wie mit der Zsh erledigen Sie einfache arithmetische Operationen, die jedoch vom Umfang der Funktionen nicht an die Möglichkeiten von externen Programmen heranreichen.
Dateiströme
Sämtliche Shells bieten die Möglichkeit, die Ausgabe von und die Eingabe in Programme(n) umzuleiten und mittels Pipes zu verknüpfen:
ls -la | grep "readme" | more
Alternativ zum Befehl echo bieten alle Shells noch das eingebaute Kommando printf, das die Inhalte von Variablen in einen Text einbaut:
printf "Name: %s Alter: %d" $name $alter
Wie in der gleichnamigen Funktion aus der Programmiersprache C bringen Sie an den entsprechenden Stellen Platzhalter unter, welche die Shell durch die Werte aus den Variablen ersetzt.
Kontrollstrukturen
Den Ablauf innerhalb eines Skripts steuern Entwickler über entsprechende Kontrollstrukturen und Schleifen. Jede Shell nutzt dabei jedoch eine leicht unterschiedliche Syntax. Listing 1 zeigt als Beispiel eine If-Abfrage in der Bash, der Zsh und der Fish.
Listing 1
# Bash und Zsh
if [[ $farbe == "rot" ]]; then
echo $farbe
fi
# Zsh
if [[ $farbe == "rot" ]] {
echo $farbe
}
# Fish
if test $farbe = rot
echo $farbe
end
Neben dem Schlüsselwort if bieten alle Shells außerdem eine While- und eine For-Schleife. Letztere kennen Bash und Zsh sogar in zwei verschiedenen Notationen. Die darüber hinaus im Angebot befindlichen Kontrollstrukturen und Schleifen unterscheiden sich jedoch zwischen den Shells. So offerieren die Bash und Zsh noch eine Until-Schleife, die in Fish fehlt.
Die Zsh bietet als einzige Shell eine Schleife mit Repeat an, die Befehle in einer vorgegebenen Anzahl wiederholt. Die Bash und Zsh besitzen zudem eine Select-Schleife, die ein einfach gestaltetes Menü für eine Auswahl erzeugt.
Funktionen
Sämtliche Shells erlauben es, mehrere Befehle in einer Funktion zusammenzufassen. Wie Listing 2 zeigt, verwenden die Bash und Zsh dazu eine identische Syntax, die Fish geht wieder einen komplett eigenen Weg.
Listing 2
# Bash und Zsh
sagwas() {
echo "Hallo!"
}
# Bash und Zsh (alternativ)
function sagwas {
echo "Hallo!"
}
# Fish
function sagwas
echo "Hallo!"
end
Hier gelingt zudem der Zugriff auf eine Variable stets nur in dem Kontext, in dem Sie sie definiert haben. Verwenden Sie die Bash oder die Z-Shell, sind nur diejenigen Variablen lokal, die Sie explizit als local kennzeichnen:
local name = "Peter"
Die Z-Shell erlaubt außerdem anonyme Funktionen, die keinen Namen besitzen. Eine solche Funktion führt die Shell sofort aus, sobald sie im Code über deren Definition stolpert. Das lässt sich beispielsweise bestens dazu nutzen, um in Start-Skripten die Sichtbarkeit von Variablen auf den Funktionsrumpf zu beschränken.
Ausgelagert
Zsh und Fish sind in der Lage, die von einem Skript benutzten Funktionen automatisch aus separaten Dateien nachzuladen. Dieser Autoload-Mechanismus unterscheidet sich allerdings in beiden Shells leicht.
So müssen Sie etwa in der Zsh die entsprechenden Funktionen zunächst explizit mit dem Schlüsselwort autoload anmelden. Diese Shell erlaubt es außerdem, den Funktionsumfang über sogenannte Module zu erweitern, diese Sie bei Bedarf sogar zur Laufzeit nachladen. Einige davon bringt die Shell bereits mit: So fügt etwa das Modul zsh/zftp einen vollständigen FTP-Client hinzu.
Über das eingebaute Kommando compile vermag die Z-Shell Funktionen und Skripte zu übersetzen und in einer Binärdatei zu speichern. Das Ergebnis lädt dann zwar schneller, für andere Shells ist es jedoch nutzlos.
Wissenslager
Die Entwickler der Bash stellen auf ihrer Website eine umfassende Referenz bereit, die sich aber recht technisch und trocken liest [8]. Einen besseren Einstieg vermitteln Tutorials wie der immer noch gültige Advanced Bash-Scripting Guide [9]. Das Bash Hackers Wiki sammelt zudem zahlreiche Anleitungen und weiterführende Links [10].
Für Z-Shell-Nutzer bildet die offizielle Homepage die erste Anlaufstelle [11]. Dort finden sich neben einer unübersichtlichen Referenz zahlreiche Links zu weiteren Informationsquellen. Zu Letzteren gehört ein User Guide, den allerdings schon seit Längerem niemand mehr aktualisiert hat und der zudem lückenhaft ausfällt [12].
Die Fish-Entwickler bieten auf ihrer Website ein ausführliches Tutorial sowie eine Referenz an, bei der jedoch immer wieder Fragen offenbleiben [13]. Anders als bei der Bash existieren zu Fish und Zsh keine alternativen Anleitungen. Auf die Zsh treffen Sie allerdings hin und wieder in Büchern zur Shell-Programmierung.
Busybox
Ein wenig aus dem Rahmen fällt die unter der GPLv2 stehende Busybox [14]. Bereits Mitte der 1990er-Jahre entwickelt, vereint sie häufig benötigte Werkzeuge für die Kommandozeile in einem kompakten Programm. So listet etwa der Befehl busybox ls alle Dateien im aktuellen Verzeichnis auf, während busybox mkdir briefe das Verzeichnis briefe erstellt. Die aktuelle Busybox-Version 1.28.1 integriert außerdem die beiden Shells Ash und Hush.
Durch das Bündeln der Befehle in einem einzigen Programm eignet sich Busybox vor allem für den Einsatz auf Embedded-Geräten. Um dort Speicherplatz zu sparen, integriert es eigene, modifizierte oder abgespeckte Fassungen der sonst auf Linux-Systemen üblichen GNU-Anwendungen. Darüber hinaus besteht die Möglichkeit, beim Übersetzen des Quellcodes einzelne Bestandteile und Funktionen abzuschalten. Das erlaubt es etwa, die Ash um den eingebauten Printf-Befehl zu berauben und die Hush komplett zu entfernen.
Es hängt allerdings vom jeweiligen System ab, welche Shells überhaupt bereitstehen und welche Funktionen diese im Einzelnen anbieten. Sofern Sie die Busybox nicht selbst übersetzt haben, bleibt Ihnen folglich nur übrig, auf eine Dokumentation des Anbieters zu hoffen oder umständlich mit Tests den Funktionsumfang selbst herauszufinden. Erschwerend kommt hinzu, dass die Entwickler weder die eingebaute Ash noch die Hush dokumentieren. Bekannt ist lediglich, dass es sich bei der Ash tatsächlich um eine modifizierte Version der Dash handelt.
Ein Blick in den Quellcode verrät, dass die Hush derzeit noch zahlreiche Baustellen besitzt. Obendrein entspricht Sie nicht mehr der originalen Fassung von Larry Doolittle aus dem Jahr 2001, sondern erhielt vom Busybox-Projekt einige zusätzliche Funktionen spendiert. Die stammen teilweise aus der Shell Lash, die noch in älteren Versionen von Busybox zur Auswahl stand. Möchten Sie bestehende Shell-Skripte unter der Busybox betreiben, empfiehlt es sich daher, die Ash zu wählen und sich auf umfangreiche Änderungen an den Skripten einzustellen (Abbildung 4).

Abbildung 4: Schon beim Übersetzen dürfen Sie die Funktionen der Shells in der Busybox nach Ihren Bedürfnissen festlegen.
Fazit
Bash, Fish und Zsh bieten einen ähnlichen Funktionsumfang, weichen aber in vielen Details voneinander ab. Das gilt insbesondere für die Syntax der Kontrollstrukturen. Aus diesem Grund laufen nur extrem simple Skripte auf Anhieb unter einer anderen Shell.
Wollen Sie ein Skript auf möglichst vielen Systemen verwenden, führt an der Bash kein Weg vorbei: Sie ist in der Regel vorinstalliert und besitzt obendrein die meisten Nutzer. Bei Problemen oder Fragen finden Sie so meist rasch Hilfe im Netz.
Spielt die Portabilität keine oder nur eine untergeordnete Rolle, sollten Sie sich am jeweiligen Angebot der Shells orientieren. Falls Sie beispielsweise über die Kommandozeile der Shell ausschließlich Programme starten, dann dürften die automatischen Vorschläge der Fish Ihnen vermutlich einiges an Tipparbeit ersparen.
Infos
- Bash: http://www.gnu.org/software/bash/
- Korn-Shell: http://www.kornshell.org
- Dash: http://gondor.apana.org.au/~herbert/dash/
- Z-Shell: http://www.zsh.org
- Fish: https://fishshell.com
- “The Open Group Base Specifications Issue 7, 2018 edition”: http://pubs.opengroup.org/onlinepubs/9699919799/nfindex.html
- Bash-POSIX-Modus: http://www.gnu.org/software/bash/manual/bash.html#Bash-POSIX-Mode
- Bash-Handbuch: http://www.gnu.org/software/bash/manual/
- Advanced Bash Scripting Guide: http://tldp.org/LDP/abs/html/
- Bash Hackers Wiki: http://wiki.bash-hackers.org/start
- Z-Shell-Dokumentation: http://zsh.sourceforge.net
- User Guide zur Z-Shell: http://zsh.sourceforge.net/Guide/
- Fish-Dokumentation: https://fishshell.com/docs/current/index.html
- Busybox: https://busybox.net






