Die Bourne Again Shell ist ein POSIX-konformer Interpreter für Programme wie dieses:
:(){ :|: & };:
Wenn die bash(1)
als interaktive Shell in einer
Terminal-Emulation startet, dann liest sie nur die globale Konfiguration
/etc/bash.bashrc
und die benutzereigene
~/.bashrc
.
Ein Skript besteht aus einer Folge von Kommandos.
Die erste Zeile kann (und sollte) einen speziellen Kommentar (shebang
)
enthalten, welches den zu verwendenen Interpreter enthält.
hello.sh#!/usr/bin/env bash if [ $# -eq 0 ] then echo Hello, World\! else for arg do echo Hello, $arg\! done fi
Ausführbar machen und ausführen mit:
chmod +x hello.sh && ./hello.sh Hello, World!
Ein Kommando besteht aus dem Namen einer
Funktion oder eines Programms gefolgt von einer Liste mit Argumenten.
In Shellskripten wird die Argumentliste in den Positionsparametern
gespeichert. In C-Programmen greift man auf die Argumentliste über
den Parameter argv
der Funktion main
zu.
Programm | Option | Option | Parameter | Operand | |
Kommandozeile | mkdir | -p | -m | 755 | ~/foo/bar |
Positionsparameter | $0 | $1 | $2 | $3 | $4 |
Argumentliste in C | argv[0] | argv[1] | argv[2] | argv[3] | argv[4] |
Ein Argument,
das mit einem -
beginnt, nennt man Option.
Manche Optionen haben wiederum Parameter (optarg
).
Sie steuern üblicherweise das Verhalten des Programms. Das Programm
getopts
extrahiert alle Optionen aus der Argumentliste.
Übrig bleiben die Operanden, mit denen das Programm arbeitet.
Die Shell verwaltet (wie jeder Prozess) eine Liste von Variablen, die sogenannte Umgebung (environment). Exportierte Variablen vererbt sie an Kindprozesse. Folgende Variablen stehen in jedem Skript zur Verfügung:
0…9
*
"$1 $2 …"
@
"$1" "$2" …
#
?
-
$
!
_
RANDOM
Einige Umgebungsvariablen setzt bereits das Anmeldeprogramm login(1)
,
andere werden durch Konfigurationsdateien festgelegt und manche dynamisch angepasst,
zum Beispiel wenn sich die Größe des Terminal-Fensters ändert.
Viele Programme wie zum Beispiel man(1)
oder
crontab(1)
honorieren bestimmte Variablen, um ihr
Verhalten anzupassen.
Variable | Beispiel | Quelle | Beschreibung |
---|---|---|---|
LOGNAME | phrank | /etc/passwd | Benutzername (System V) |
USER | phrank | " | Benutzername (BSD) |
HOME | /home/phrank | " | Benutzerverzeichnis |
SHELL | /bin/bash | " | Kommandointerpreter |
LANG | de_DE.UTF-8 | pam_env.so | Internationalisierung |
PATH | /usr/local/bin:… | /etc/profile | Programmsuchpfad |
PS1 | \u@\h:\w\$ | /etc/bash.bashrc | Eingabeaufforderung |
PAGER | less | ~/.bashrc | Anzeigeprogramm |
EDITOR | joe | " | Texteditor |
MAILER | thunderbird | " | Elektropost |
BROWSER | firefox | " | Navigator |
TERM | xterm | xterm | Terminaltyp |
LINES | 25 | " | Zeilenhöhe |
COLUMNS | 80 | " | Spaltenbreite |
PWD | $(pwd) | bash | Arbeitsverzeichnis |
Eine Variable hat einen Namen und einen Wert. Eine Reihung (array) verhält sich wie eine Streutabelle (hashmap) mit numerischen Schlüsseln. Die Bash erlaubt seit Version 4 auch Zeichenketten als Schlüssel.
null= path="/foo/bar.txt" array=(foo bar fnord) declare -A hash=([foo]=fnord [bar]=snafu)
Das Symbol $
steht für Substitution.
Findet die Shell diesen Operator, expandiert sie die entsprechende Variable nach den
unten beschriebenen Regeln, bevor sie das Kommando ausführt.
Variable | Beispiel | Ausgabe | Expansion |
---|---|---|---|
$Name | $path | /foo/bar.txt | Wert der Variable |
${Name} | ${path}_ | /foo/bar.txt_ | Dito |
${Name:Pos} | ${path:4} | bar.txt | Ab dem sovielten Zeichen |
${Name:Pos:Len} | ${path:4:3} | bar | Ab dem sovielten Zeichen mit Länge |
${#Name} | ${#path} | 12 | Länge des Werts |
Ersetzung | |||
${Name#Prefix} | ${path#*/} | foo/bar.txt | Präfix abschneiden |
${Name##Prefix} | ${path##*/} | bar.txt | Präfix gierig abschneiden (basename ) |
${Name%Suffix} | ${path%/*} | /foo | Suffix abschneiden (dirname ) |
${Name%%Suffix} | ${path%%/*} | Suffix gierig abschneiden | |
${Name/Glob/Repl} | ${path/o/l} | /flo/bar.txt | Einmal ersetzen |
${Name//Glob/Repl} | ${path//o/u} | /fuu/bar.txt | Alle ersetzen |
${Name/#Glob/Repl} | ${path/#\/foo/fnord} | fnord/bar.txt | Vorne ersetzen |
${Name/%Glob/Repl} | ${path/%txt/jpg} | /foo/bar.jpg | Hinten ersetzen |
Null-Variable | |||
${Name:+Text} | ${path:+hello} | Alternative oder gar nichts. | |
${Name:-Text} | ${path:-hello} | /foo/bar.txt | Defaultwert |
${Name:=Text} | ${null:=hello} | hello | Defaultwert mit Zuweisung an Variable |
${Name:?Text} | ${null:?hello} | hello | Meldung auf stderr ; beendet die Shell |
Variablennamen | |||
${!Prefix*} | ${!p*} | path | Variablennamen mit Präfix als Token |
${!Prefix@} | ${!p@} | path | Variablennamen mit Präfix als Liste |
Reihung | |||
${Array[*]} | ${array[*]} | foo bar fnord | Werte als Token |
${Array[@]} | ${array[@]} | foo bar fnord | Werte als Liste |
${!Array[*]} | ${!array[*]} | 1 2 3 | Schlüssel als Token |
${!Array[@]} | ${!array[@]} | 1 2 3 | Schlüssel als Liste |
${#Array[@]} | ${#array[@]} | 3 | Anzahl der Elemente |
${#Array[Key]} | ${#array[2]} | 5 | Länge des Elements |
${Array[Key]} | ${array[2]} | fnord | Wert des Elements |
Kommando-Substitution | |||
`Command` | `uname` | Linux | Ausgabe des Kommandos, veraltet |
$(Command) | $(uname) | Linux | Ausgabe des Kommandos |
<(Command) | <(uname) | Ausgabe von Kommando Umleiten | |
>(Command) | >(uname) | Ausgabe zu Kommando Umleiten | |
Arithmetik | |||
$((Expression)) | $((x + 3)) | 8 | Arithmetische Erweiterung |
Wert-Expansion (Klammer, Tilde, Datei) | |||
{Char..Char} | foo{a..c} | fooa foob fooc | Kombinationen mit einer Spanne von Zeichen |
{String,…} | foo{bar,baz} | foobar foobaz | Kombinationen mit einer Liste von Zeichenketten |
~ | ~ | /home/bob | Benutzerverzeichnis des Prozessbesitzers |
~User | ~alice | /home/alice | Benutzerverzeichnis eines anderen Benutzers |
* | foo* | foo foo.txt | Beliebige Zeichenkette |
? | ?oo | foo xoo zoo | Beliebiges Zeichen |
[List] | [a-m,x,y]oo | foo xoo | Ein Zeichen aus einer Gruppe |
Command && Command || Command
if [[ Expression ]]; then …; [ elif [[ Expression ]]; then …; else …; ] fi
case Name in Glob) …;; esac
while [[ Expression ]]; do …; done
until [[ Expression ]]; do …; done
for Name; do …; done
for Name in List; do …; done
for ((Expr1; Expr2; Expr3)); do …; done
break
for
-, while
- oder until
-Schleifecontinue
Name() { … }
return ExitCode
trap Command Signal …
[[ Expression ]]
Operand | Operator | Operand | Wahr, wenn |
---|---|---|---|
Lexikographisch | |||
-z | String | Zeichenkette leer ist | |
-n | String | Zeichenkette mindestens ein Zeichen enthält | |
String | = | String | Zeichenketten identisch sind |
String | == | String | Dito |
String | != | String | Zeichenketten sich unterscheiden |
String | < | String | Linke lexikographisch kleiner als rechte Zeichenkette |
String | > | String | Linke lexikographisch größer als rechte Zeichenkette |
Arithmetisch | |||
! | Expression | Negation, Ausdruck ist falsch | |
Number | -eq | Number | Gleichheit |
Number | -ne | Number | Ungleichheit |
Number | -lt | Number | Linke Zahl kleiner als rechte Zahl |
Number | -le | Number | Linke Zahl kleiner oder gleich rechte Zahl |
Number | -gt | Number | Linke Zahl größer als rechte Zahl |
Number | -ge | Number | Linke Zahl größer oder gleich rechte Zahl |
(( Expression ))
Operand | Operator | Operand | Wahr, wenn |
---|---|---|---|
(…) | Präzedenz | ||
Number | = | Number | Zuweisung |
Number | += | Number | Zuweisung mit Addition |
++ | Number | Increment | |
-- | Number | Decrement | |
~ | Number | Bitkomplement | |
Number | & | Number | Bitweise UND verknüpfen |
Number | ^ | Number | Bitweise ODER verknüpfen |
Number | ** | Number | Exponent |
Number | * | Number | Multiplikation |
Number | / | Number | Division |
Number | % | Number | Modulo |
Number | + | Number | Addition |
Number | - | Number | Subtraktion |
Eine Pipe verbindet die
Standardausgabe eines Prozesses mit der Standardeingabe des Nächsten.
Typische Unix-Programme sind dafür ausgelegt, entweder
als Quelle (cat
, ls
),
als Filter (grep
, sort
)
oder als Senke (less
, lpr
) zu agieren.
Source | Filter | Sink
(Standard)eingabe | |||
---|---|---|---|
Command | [n]< | File | Aus Datei lesen |
Command | [n]<< | Delimiter | Bis zum Trenner lesen (Here-Dokument) |
Command | [n]<<- | Delimiter | Dito, aber Einrückung ignorieren |
Command | [n]<&[n] | Deskriptor duplizieren | |
Command | [n]<&- | Deskriptor schließen | |
(Standard)ausgabe | |||
Command | [n]> | File | In Datei schreiben |
Command | [n]>| | File | Datei überschreiben, selbst wenn noclobber gesetzt ist |
Command | [n]>> | File | An Datei anhängen |
Command | [n]>&[n] | Deskriptor duplizieren | |
Command | [n]>&- | Deskriptor schließen | |
Command | [n]<> | File | Deskriptor zum Lesen und Schreiben öffnen |
0 | Standardeingabe |
1 | Standardausgabe |
2 | Standardfehlerausgabe |
Standardfehlerausgabe im Pager betrachten
Command 2>&1 | less
Der Operator >
leitet die Ausgabe von Kommandos
und Funktionen in Dateien um.
for i in {1..10}; do echo "Hello $i"; done > File
Umgekehrt leitet <
den Inhalt von Dateien
in die Standardeingabe um. Um zum Beispiel eine Datei zeilenweise
zu lesen:
while read line; do echo $((++n)) $line; done < File
Und so leitet man die Standardausgabe eines Kommandos in die Standardeingabe um:
while read line; do echo $line; done < <(Command)
Umleitung eines Here-Dokuments in ein Kommando:
cat <<- . the quick brown fox jumps over the lazy dog .
Per Kontrollsequenz lassen sich die Position der Eingabemarke sowie typografische Merkmale wie Fettdruck, Unterstreichungen, Vorder- und Hintergrundfarben ändern.
echo -e "\e[32;1mHallo, Welt\e[0m" Hallo, Welt
Code | Name | ASCII | Beschreibung |
---|---|---|---|
\a | BEL | 7 | Alarm |
\b | BS | 8 | Backspace |
\t | HT | 9 | Horizontaler Tabulator |
\n | LF | 10 | Newline |
\v | VT | 11 | Vertikaler Tabulator |
\f | FF | 12 | Form feed |
\r | CR | 13 | Carriage return |
\e | ESC | 27 | Escape |
\\ | 92 | Backslash ausgeben | |
\c | Weitere Ausgabe unterdrücken | ||
\0{0…7}{0…7} | Oktal | ||
\x{0…f}{0…f} | Hexadezimal | ||
\u{0…f}..{0…f} | Unicode | ||
\U{0…f}......{0…f} | Unicode erweitert |
Der CSI (ESC+[) leitet Befehle zur Steuerung der Eingabemarke ein.
Sequenz | Name | Beschreibung | |
---|---|---|---|
\e[UpA | CUU | Schritt nach Oben | |
\e[DownB | CUD | Schritt nach Unten | |
\e[RightC | CUF | Schritt nach Rechts | |
\e[LeftD | CUB | Schritt nach Links | |
\e[LineE | CNL | Sprung an Zeilenanfang weiter unten | |
\e[LineF | CPL | Sprung an Zeilenanfang weiter oben | |
\e[ColumnG | CHA | Setzen auf Spalte | |
\e[Row;ColumnH | CUP | Setzen auf absolute Position | |
\e[0J | ED | Löschen ab Eingabemarke bis Seitenende | |
\e[1J | Löschen ab Seitenanfang bis Eingabemarke | ||
\e[2J | Löschen der ganzen Seite | ||
\e[0K | EL | Löschen ab Eingabemarke bis Zeilenende | |
\e[1K | Löschen ab Zeilenanfang bis Eingabemarke | ||
\e[2K | Löschen der ganzen Zeile | ||
\e[LinesS | SU | Seite nach oben rollen | |
\e[LinesT | SD | Seite nach unten rollen | |
\e[Row;Columnf | HVP | Position der Eingabemarke setzen | |
\e[Codem | SGR | Farben ändern, siehe unten | |
\e[s | SCP | Position der Eingabemarke merken | |
\e[u | RCP | Position der Eingabemarke wiederherstellen | |
\e[?25l | DECTCEM | Eingabemarke verbergen | |
\e[?25h | DECTCEM | Eingabemarke anzeigen |
SGR-Sequenzen ändern Stil und Farbe der Schrift.
Sequenz | Berechnung | Werte | Farbschema |
---|---|---|---|
\e[1m … \e[22m | Fett | ||
\e[2m … \e[22m | Dünn | ||
\e[3m … \e[23m | Kursiv | ||
\e[4m … \e[24m | Unterstrichen | ||
\e[5m … \e[25m | Blinkend | ||
\e[6m … \e[26m | Flackernd | ||
\e[7m … \e[27m | Invers | ||
\e[8m … \e[28m | Unsichtbar | ||
\e[9m … \e[29m | Durchgestrichen | ||
\e[30…37;40…47m | Blue*4+Green*2+Red+30 | 8 ANSI Farben | |
\e[38;5;Fore;48;5;Backm | Red*36+Green*6+Blue+16 | 0…5 | 216 SGR-Farben |
232+{0…23} | 0…23 | 24 SGR Graustufen | |
\e[38;2;Red;Green;Blue;m | 0…255 | 16 Millionen Echtfarben | |
\e[48;2;Red;Green;Blue;m | 0…255 | 16 Millionen Hintergründe |
# | B | G | R | Farbe |
---|---|---|---|---|
30 | 0 | 0 | 0 | Schwarz |
31 | 0 | 0 | 1 | Rot |
32 | 0 | 1 | 0 | Grün |
33 | 0 | 1 | 1 | Gelb |
34 | 1 | 0 | 0 | Blau |
35 | 1 | 0 | 1 | Magenta |
36 | 1 | 1 | 0 | Cyan |
37 | 1 | 1 | 1 | Weiß |
OSC-Sequenzen (ESC+]) können unter anderem das Icon und den Titel eines grafischen Terminals setzen.
\e]0;Icon Title\e\\ \e]1;Icon\e\\ \e]2;Title\e\\
Praktischerweise führt die Bash bei der Anzeige der
Eingabeaufforderung (prompt)
immer das in der Variablen PROMPT_COMMAND
gespeicherte
Kommando aus, so dass man zum Beispiel immer das Arbeitsverzeichnis
ausgeben kann.
PROMPT_COMMAND='echo -ne "\e]2;$LOGNAME@$HOSTNAME:$PWD\e\\"'
Fortgeschrittene Terminal-Emulationen (VT240 aufwärts) unterstützen das DEC SIXEL Format und die ReGIS Vektorsprache.
apt install mlterm libsixel-bin mlterm![]()