Bash-Spickzettel
Syntax zum Nachschlagen, ohne Erklärungen. Die Herleitung findest du in Modul 7 und Modul 8. Alle Beispiele setzen Bash 5 voraus und sind ShellCheck-sauber.
Spezialvariablen
Abschnitt betitelt „Spezialvariablen“| Variable | Bedeutung |
|---|---|
$0 |
Name des Skripts (so wie es aufgerufen wurde) |
$1 $2 … $9 ${10} |
Positionsparameter, ab 10 mit geschweiften Klammern |
$# |
Anzahl der Positionsparameter |
"$@" |
Alle Parameter, jeder einzeln gequotet. Fast immer das Richtige |
"$*" |
Alle Parameter als ein Wort, getrennt durch das erste Zeichen von IFS |
$? |
Exit-Status des letzten Befehls (0 = Erfolg) |
$$ |
PID der aktuellen Shell |
$! |
PID des zuletzt gestarteten Hintergrundprozesses |
$_ |
Letztes Argument des vorherigen Befehls |
$- |
Aktive Shell-Optionen, zum Beispiel himBHs |
$IFS |
Feldtrenner, Standard: Leerzeichen, Tab, Zeilenumbruch |
$LINENO |
Aktuelle Zeilennummer im Skript |
$RANDOM |
Zufallszahl 0 bis 32767 |
$SECONDS |
Sekunden seit Start der Shell |
$HOME $USER $PATH $PWD $SHELL |
Umgebung |
shift |
$2 wird $1, $# sinkt um eins (shift 2 für zwei) |
Tests mit [[ ]]
Abschnitt betitelt „Tests mit [[ ]]“In Bash-Skripten [[ ]] verwenden (keine Wortaufteilung, && und || erlaubt, Muster möglich). [ ] ist das POSIX-Builtin test.
Dateien
| Test | Wahr, wenn |
|---|---|
[[ -e pfad ]] |
existiert (beliebiger Typ) |
[[ -f pfad ]] |
reguläre Datei |
[[ -d pfad ]] |
Verzeichnis |
[[ -L pfad ]] |
symbolischer Link |
[[ -r pfad ]] -w -x |
lesbar, schreibbar, ausführbar für dich |
[[ -s pfad ]] |
existiert und ist nicht leer |
[[ a -nt b ]] / -ot |
a neuer als b / älter als b |
Strings
| Test | Wahr, wenn |
|---|---|
[[ -z "$s" ]] |
leer |
[[ -n "$s" ]] |
nicht leer |
[[ "$a" == "$b" ]] |
gleich |
[[ "$a" != "$b" ]] |
ungleich |
[[ "$a" == abc* ]] |
passt auf Glob-Muster (rechte Seite ungequotet) |
[[ "$a" =~ ^[0-9]+$ ]] |
passt auf regulären Ausdruck, Gruppen in BASH_REMATCH |
[[ "$a" < "$b" ]] |
alphabetisch davor |
Zahlen
| Test | Bedeutung |
|---|---|
[[ "$a" -eq "$b" ]] |
gleich |
[[ "$a" -ne "$b" ]] |
ungleich |
[[ "$a" -lt "$b" ]] / -le |
kleiner / kleiner gleich |
[[ "$a" -gt "$b" ]] / -ge |
grösser / grösser gleich |
(( a < b )) |
Arithmetischer Vergleich, lesbarer, kein $ nötig |
Verknüpfen
[[ -f "$datei" && -r "$datei" ]][[ "$n" -lt 1 || "$n" -gt 10 ]][[ ! -d "$dir" ]]Parameter-Expansion
Abschnitt betitelt „Parameter-Expansion“| Ausdruck | Ergebnis |
|---|---|
${var} |
Wert von var, Klammern trennen vom Folgetext: ${var}_backup |
${var:-wert} |
var falls gesetzt und nicht leer, sonst wert (ohne Zuweisung) |
${var:=wert} |
Wie oben, weist wert zusätzlich zu |
${var:?meldung} |
Bricht mit meldung ab, wenn var leer ist |
${var:+wert} |
wert, falls var gesetzt ist, sonst leer |
${#var} |
Länge des Strings |
${var#muster} |
Kürzestes muster am Anfang entfernen: ${pfad#*/} |
${var##muster} |
Längstes muster am Anfang entfernen: ${pfad##*/} ergibt den Dateinamen |
${var%muster} |
Kürzestes muster am Ende entfernen: ${datei%.*} ergibt den Namen ohne Endung |
${var%%muster} |
Längstes muster am Ende entfernen: ${pfad%%/*} |
${var/alt/neu} |
Erstes Vorkommen ersetzen |
${var//alt/neu} |
Alle Vorkommen ersetzen |
${var^} / ${var^^} |
Erster Buchstabe / alle Buchstaben gross |
${var,} / ${var,,} |
Erster Buchstabe / alle Buchstaben klein |
${var:2:3} |
Teilstring ab Position 2 (nullbasiert), 3 Zeichen lang |
${var: -3} |
Letzte drei Zeichen (Leerzeichen vor dem Minus ist Pflicht) |
${!var} |
Indirekt: Wert der Variablen, deren Name in var steht |
${!prefix*} |
Namen aller Variablen, die mit prefix beginnen |
pfad="/home/alice/bericht.final.txt"echo "${pfad##*/}" # bericht.final.txtecho "${pfad%/*}" # /home/aliceecho "${pfad%.*}" # /home/alice/bericht.finalecho "${pfad##*.}" # txtArithmetik
Abschnitt betitelt „Arithmetik“zaehler=$(( zaehler + 1 )) # sicher mit set -e, siehe unten(( summe += wert ))ergebnis=$(( (a + b) * 2 ))rest=$(( a % b ))if (( a > b )); then echo "a ist grösser"; fifor (( i = 0; i < 5; i++ )); do echo "$i"; doneNur Ganzzahlen. Operatoren: + - * / % **, Vergleiche < <= > >= == !=, logisch && || !. Für Kommazahlen bc: echo "scale=2; 10/3" | bc.
farben=(rot gruen blau) # anlegenfarben+=(gelb) # anhängenecho "${farben[0]}" # erstes Elementecho "${farben[-1]}" # letztes Elementecho "${farben[@]}" # alle Elemente, einzeln gequotetecho "${#farben[@]}" # Anzahlecho "${!farben[@]}" # Indizesunset 'farben[1]' # Element entfernenfor f in "${farben[@]}"; do echo "$f"; done
declare -A alter # assoziatives Array (Hash)alter[alice]=30alter[bob]=25echo "${alter[alice]}"for name in "${!alter[@]}"; do echo "$name: ${alter[$name]}"; done
mapfile -t zeilen < datei.txt # Datei zeilenweise in Array lesenKontrollstrukturen
Abschnitt betitelt „Kontrollstrukturen“# if / elif / elseif [[ bedingung ]]; then befehleelif [[ bedingung ]]; then befehleelse befehlefi
# casecase "$wahl" in 1|a) befehle ;; [Jj]*) befehle ;; *) echo "unbekannt" ;;esac
# for über Listefor datei in *.txt; do echo "$datei"done
# for über Zahlenbereichfor i in {1..10}; do echo "$i"; donefor i in $(seq 1 2 10); do echo "$i"; done
# whilewhile [[ "$n" -gt 0 ]]; do (( n-- ))done
# untiluntil ping -c 1 -W 1 "$host" &>/dev/null; do sleep 1; done
# Datei zeilenweise lesenwhile IFS= read -r zeile; do echo "$zeile"done < datei.txt
# Endlosschleife mit Abbruchwhile true; do read -rp "Eingabe (q beendet): " eingabe [[ "$eingabe" == q ]] && breakdone
# break verlässt die Schleife, continue springt zum nächsten DurchlaufKurzformen: befehl && bei_erfolg, befehl || bei_fehler, befehl || exit 1.
Funktionen
Abschnitt betitelt „Funktionen“begruesse_benutzer() { local name="${1:-Welt}" # Parameter mit Standardwert local anzahl=$# echo "Hallo, $name ($anzahl Argumente)" return 0 # Exit-Status 0 bis 255, nicht für Daten}
hole_datum() { date +%Y-%m-%d # Rückgabe von Daten über stdout}
begruesse_benutzer "Alice"heute=$(hole_datum)Variablen in Funktionen immer mit local. Funktionen müssen vor dem ersten Aufruf definiert sein.
getopts-Skelett
Abschnitt betitelt „getopts-Skelett“usage() { echo "Benutzung: $0 [-h] [-v] [-n NAME] datei..." >&2 exit 1}
verbose=0name=""while getopts "hvn:" opt; do case "$opt" in h) usage ;; v) verbose=1 ;; n) name="$OPTARG" ;; *) usage ;; esacdoneshift $(( OPTIND - 1 )) # danach sind "$@" die restlichen Argumente
[[ $# -ge 1 ]] || usageEin Doppelpunkt hinter dem Buchstaben (n:) heisst: diese Option braucht einen Wert. Lange Optionen (--name) kann getopts nicht, dafür eine while-Schleife mit case "$1".
Umleitungen
Abschnitt betitelt „Umleitungen“| Syntax | Wirkung |
|---|---|
befehl > datei |
stdout in Datei (überschreiben) |
befehl >> datei |
stdout anhängen |
befehl 2> datei |
stderr in Datei |
befehl 2>&1 |
stderr dorthin, wo stdout gerade hingeht |
befehl > datei 2>&1 |
beides in Datei (Reihenfolge wichtig) |
befehl &> datei |
Kurzform für beides (Bash) |
befehl 2>/dev/null |
Fehler verwerfen |
befehl < datei |
stdin aus Datei |
a | b |
stdout von a wird stdin von b |
a |& b |
stdout und stderr von a nach b |
befehl | tee datei |
Ausgabe auf Bildschirm und in Datei |
befehl <<< "text" |
Here-String: Text als stdin |
diff <(ls a) <(ls b) |
Prozess-Substitution: Ausgabe als Datei |
exec > logdatei 2>&1 |
Ab hier alle Ausgaben des Skripts in Datei |
Here-Doc
Abschnitt betitelt „Here-Doc“cat <<'EOT' > "$ziel"Text wird wörtlich übernommen, $variablen bleiben stehen.EOT
cat <<EOTHallo $USER, heute ist $(date +%A).EOT
cat <<-EOT Führende Tabs (keine Leerzeichen) werden entfernt. EOTBegrenzer in Anführungszeichen ('EOT') verhindert Expansion. <<- erlaubt Einrückung mit Tabs.
set-Optionen
Abschnitt betitelt „set-Optionen“| Option | Wirkung |
|---|---|
set -e |
Skript bricht beim ersten fehlgeschlagenen Befehl ab (errexit) |
set -u |
Nicht gesetzte Variablen sind ein Fehler (nounset) |
set -o pipefail |
Pipeline scheitert, wenn ein Glied scheitert, nicht nur das letzte |
set -euo pipefail |
Die Kombination für jedes Skript im Kurs |
set -x |
Jeden Befehl vor der Ausführung anzeigen (Debugging), set +x beendet |
set -n |
Nur Syntax prüfen, nichts ausführen (bash -n skript.sh) |
shopt -s nullglob |
Muster ohne Treffer ergibt leere Liste statt dem Muster selbst |
shopt -s globstar |
** passt rekursiv auf Verzeichnisse |
Ausnahmen von -e: Befehle in if, while, &&, || und ! dürfen scheitern. Einen erwarteten Fehler fängst du so ab: grep -q muster datei || true. Falle: (( i++ )) hat den Exit-Status 1, wenn das Ergebnis 0 ist, und beendet mit set -e das Skript. Darum i=$(( i + 1 )) schreiben.
tmpdir=$(mktemp -d)cleanup() { rm -rf "$tmpdir"}trap cleanup EXIT # bei jedem Ende, auch bei Fehler oder Ctrl+Ctrap 'echo "Abbruch"; exit 130' INTtrap 'echo "Fehler in Zeile $LINENO" >&2' ERRWichtige Signale: EXIT (Skriptende), INT (Ctrl+C), TERM (kill), HUP (Terminal geschlossen), ERR (Befehl scheitert, mit set -e).
Häufige ShellCheck-Codes
Abschnitt betitelt „Häufige ShellCheck-Codes“ShellCheck prüft Skripte: shellcheck skript.sh. Jeder Code hat eine Wiki-Seite: https://www.shellcheck.net/wiki/SC2086.
| Code | Meldung (gekürzt) | Bedeutung und Lösung |
|---|---|---|
| SC2086 | Double quote to prevent globbing and word splitting | Variable ungequotet. "$var" statt $var. Der häufigste Fehler überhaupt |
| SC2046 | Quote this to prevent word splitting | Ungequotete Befehlssubstitution. "$(befehl)" |
| SC2006 | Use $(...) notation instead of legacy backticks |
Backticks sind veraltet, $(...) ist lesbar und schachtelbar |
| SC2155 | Declare and assign separately to avoid masking return values | local x=$(cmd) verschluckt den Exit-Status. Erst local x, dann x=$(cmd) |
| SC2162 | read without -r will mangle backslashes | read -r verwenden |
| SC2164 | Use cd ... || exit in case cd fails |
cd "$dir" || exit 1, sonst läuft das Skript im falschen Verzeichnis weiter |
| SC2034 | Variable appears unused | Tippfehler oder Variable nie verwendet |
| SC2068 | Double quote array expansions | "${arr[@]}" statt ${arr[@]} |
| SC2115 | Use "${var:?}" to ensure this never expands to / |
Schutz vor rm -rf "$dir/" bei leerem $dir |
| SC2148 | Tips depend on target shell, please add a shebang | Shebang fehlt |
| SC2181 | Check exit code directly | if befehl; then statt befehl; if [[ $? -eq 0 ]] |
| SC1090/SC1091 | Can’t follow non-constant source | Hinweis bei source "$datei", meist harmlos |
| SC2002 | Useless cat | grep muster datei statt cat datei | grep muster |
Eine Warnung gezielt ausschalten, wenn sie in einem Fall falsch ist:
# shellcheck disable=SC2034farbe_rot='\033[31m'