Programmieren mit der Unix-Shell
Axel Pemmann, 08.01.2026, Version 0.3
Shells
Seit der Unix-Geburt am 01.01.1970 wurde die ursprüngliche Schnittstelle zwischen Mensch und Maschine stetig weiterentwickelt, sie bekam Komfort-Funktionen und wichtige Steuerungsmechanismen für den Programmablauf beigebracht. Hier ein kleiner Überblick:
sh (Bourne-Shell, einfache Shell, keine Komfort-Funktion)
ksh (Korn-Shell, bei Sun Solaris und anderen großen Unixen zu finden)
csh (C-Shell, Syntax der C-Sprache)
bash (= DEFAULT, Bourne-Again-Shell, = verbesserte sh, viele Features und Komfort-Funktionen)
ash (Almquist-Shell, leicht verbesserte, sichere sh, z.B. bei Alpine Linux)
fish (die neue User friedly Shell, sehr empfehlenswert, aber fürs Programmieren nicht so ideal)
Grundlegendes
Zur Automatisierung von Aufgaben werden übliche Kommandozeilen in eine nomale Textdatei geschrieben. Diese Shell-Skripte
In Frage kommende Editoren (Office-Programme erzeugen unsichtbare Metadaten!!): nano, vim, micro, mcedit, kate, mousepad
sollten mit einem bestimmten Interpreter ausgeführt werden, z.B.
#!/bin/bash(Shebang, ist optional),sollten das eXecute-Recht erhalten (Cron-Skripte benötigen beides: Shebang und Ausführungsrecht),
dienen typischen Admin-Aufgaben wie Backups oder das Starten von Anwendungen,
führen die Kommando im einfachsten Fall nur im Batch-Betrieb aus (Stapelverarbeitung),
sind normale Kommandozeilen, die man mit Kontrollstrukturen versieht.
Hierbei können wir natürlich die grundlegenden Möglichkeiten der Shell einsetzen:
Umleitungen (
>,<,>>,<<,&>,2>&1)ACHTUNG Datenverlust! Mit der stdout-Umleitung
>wird eine Datei zuerst leer gemacht, danach folgt die Befüllung!)
Pipes (
|, Kommandotee)Variablen, wir unterscheiden:
Umgebungsvariablen (besitzen die export-Eigenschaft, werden automatisch vererbt. z.B.
$HOME), aufzulisten mitenvShell-Variablen (werden nicht vererbt, können aber exportiert werden, z.B.
myname="Hans im Glück"), aufzulisten mitset
Jobverwaltung (ans Kommando das Ampersand-Zeichen
&anhängen, außerdembg,fg,jobs)Kommandozeilen ohne Erfolgsprüfung mit Semikolon nacheinander ausführen (z.B.
date ; df -h /)Aliase, z.B.
alias rm='rm -i'
Die stdin-Umleitung mit < kann vom Prinzip her ebenfalls anhängend
arbeiten, gern in Setup-Skripten eingesetzt. Die zwei <<MUSTER nennt
sich here-Document. Ein Beispiel:
tux@deb13:~$ # Configs on-the-fly zu erzeugen:
tux@deb13:~$ cat > /tmp/new-hosts <<\ABC
> 127.0.0.1 localhost
> 192.168.2.252 windows11
> ABC
tux@deb13:~$
tux@deb13:~$ cat /tmp/new-hosts
127.0.0.1 localhost
192.168.2.252 windows11
tux@deb13:~$
Siehe zu grundlegender Shell-Arbeitsweise auch:
https://pemmann.de/doc-html/_build/html/grdl/linux.html#kommandozeile
https://pemmann.de/doc/LPI-102-Handout/lpi-102-vorbereitung.html#_shells_skripte_und_datenverwaltung
Maskierung von Sonderzeichen
Das auch als Quoting bezeichnete Schützen von der Interpretation von Metazeichen:
Zeichenkette deklarieren, wobei mehrere Ersetzungen möglich sind: in Double-Tickmarks einschließen:
mkdir "Eigene Dateien für $LOGNAME"(ls -lzeigt u.a.Eigene Dateien für root)Zeichenkette deklarieren, wobei KEINE Ersetzungen möglich sein sollen: in Simple-Tickmarks einschließen (dt.: Hochkomma, Apostroph):
mkdir 'Eigene Dateien für $LOGNAME'(ls -lzeigt u.a.Eigene Dateien für $LOGNAME)Nur das eine, auf einen Backslash folgende Zeichen schützen, es dürfen ebenfalls KEINE Ersetzungen stattfinden:
echo "Mein Heimatverzeichnis steht in der Variablen \$HOME und hat den Inhalt $HOME"
Zeichenkettenschutz kann verschachtelt werden, außen herum Double-Tickmarks verwenden, innerhalb müssen dann aber Simple-Tickmarks verwendet werden (oder umgekehrt). Die Shell muss die Strings erkennen können.
Substitution, Expansion
Neben komplexen neuen Möglichkeiten wie der arithmetischen Expansion gibt es drei grundlegende Verfahren:
Dateinamensexpansion (Dateijoker, Wildcard)
Variablenersetzung
Kommandozeilensubstitution
Diese drei Verfahren werden wir nun in den folenden Abschnitten besprechen.
Dateinamensexpansion (Dateijoker, Wildcard)
Stern (
*): beliebig lange Zeichenkette beliebiger Zeichen, auch kein ZeichenFragezeichen (
?): nur ein beliebiges Zeichen, aber eins muss sein!Eckige Klammern für Zeichenklassen, ist ein Platzhalter für nur ein einzelnes Zeichen (z.B. alle Buchstaben, groß oder klein geschrieben:
[a-zA-Z])
Beispiele:
Alle Dateien unterhalb /etc auflisten, die mit “ho” beginnen:
ls /etc/ho*(trifft hier die /etc/hostname und die /etc/hosts)Alle Dateien unterhalb /etc auflisten, die mit “passwd” beginnen, worauf ein beliebiges Zeichen folgen muss:
ls /etc/passwd?(Achtung: nicht löschen, ist ein Datenbank-File!)Alle Dateien unterhalb /etc auflisten, die typische Endungen für Konfigurationsdateien aufweisen:
ls /etc/*[nf][fg]
Variablenersetzung
Für den Login werden Umgebungsvariablen benötigt, siehe Kommando
env, z.B.echo $HOMEoderecho $PATHEigene Variablen erzeugen, die anderes als die Umgebungsvariablen die Export-Eigenschaft aufweisen (sind in Sub-Shells nicht vorhanden!), siehe:
#!/bin/bash
myname="Axel Pemmann in $HOME"
echo $myname
declare -p myname # kein "x" zu sehen, d.h. die Export-Eigenschaft fehlt
export myname
declare -p myname # zeigt jetzt "-x"
# Beim Erstellen einer Variable den Typ "Integer" mitgeben:
declare -i zahl=4711
#
echo $zahl # es kommt 4711 zum Vorschein
#
zahl="Hallo" # Fläschlicherweise ein Update des Inhaltes mit einer Zeichenkette versuchen
#
echo $zahl # es kommt 0 zum Vorschein (die Zeichenkette wurde nicht akzeptiert, als Inhalt wurde eine Null gesetzt)
In der DOS-Shell setzt man übrigens die Variablen in %-Zeichen, so kann
der eigene Benutzername auf diese Weise ausgegeben werden:
echo %USERNAME%
Kommandozeilensubstitution
Es gibt zwei Varianten, um anzugeben, was zuerst ausgeführt werden soll (und dann der Rest der Zeile ringsherum):
Althergebracht, nicht verschachtelbar, mit Back-Tickmarks:
echo `date +%F` # Wir erhalten "2025-11-21"
Neue Methode, verschachtelbar:
echo $(date +%F) # Wir erhalten wiederum "2025-11-21" # Ein Backup von /etc mit Zeitstempel im Dateinamen erzeugen: tar czf etc-archiv-$(date +%F_%H-%M).tar.gz /etc
Funktionen
Eine Funktion kann als eine Art Unterprogramm betrachtet werden, bietet allerdings nicht so viele Möglichkeiten, wie die von Hochsprachen. Hier ein paar Merkmale:
Sie gestatten die Übergabe von Parametern (Shell-Aliase können das nicht!)
Man kann den Return-Code (Fehlercode) auswerten
Es lässt sich damit doppelter Code vermeiden, Skripte werden damit lesbarer
Sie können beim Login von Usern hilfreich sein (in rc-Skripte integrierbar)
tux@deb12:~ $ function hilfe(){
> echo Benutzung: hilfe
> echo "Können wir helfen?"
> echo "Heute ist $(date +%A)."
> }
tux@deb12:~ $
tux@deb12:~ $ declare -f hilfe
hilfe ()
{
echo Benutzung: hilfe;
echo "Können wir helfen?";
echo "Heute ist $(date +%A)."
}
tux@deb12:~ $
tux@deb12:~ $ # Bei Bedarf rufen wir sie wie ein Kommando auf:
tux@deb12:~ $ hilfe
Benutzung: hilfe
Können wir helfen?
Heute ist Freitag.
tux@deb12:~ $
Nun testen wir aber mal die Parameterübergabe einer Funktion, $1 ist
der erste Übergabeparameter, den wir ihr mitgeben.
tux@deb12:~$ ll
-bash: ll: Kommando nicht gefunden.
tux@deb12:~$ # >>> schön, sowas gibt es hier NOCH nicht.
tux@deb12:~$
tux@deb12:~$ function ll () { ls -ltrc $1 | tail -5; }
tux@deb12:~$
tux@deb12:~$ declare -f ll
ll ()
{
ls --color=auto -ltrc $1 | tail -5
}
tux@deb12:~$
Es gibt insgesamt drei Syntaxvarianten, einmal kann man das Schlüsselwort “function” weglassen und zum anderen die runden Klammern:
tux@deb13:~/bin$ function hallo1(){ echo Hallo Nr 1...;}
tux@deb13:~/bin$ hallo2(){ echo Hallo Nr 2...;}
tux@deb13:~/bin$ function hallo3 { echo Hallo Nr 3...;}
Hinweise für solche Einzeiler:
Nach der öffnenden geschweiften Klammer muss ein Leerzeichen stehen
Vor der schließenden geschweiften Klammer muss ein Semikolon stehen
In der dritten Variante ohne runde Klammern muss ein Leerzeichen nach dem Funktionsnamen stehen
Parameterübergabe
Übergabe-/Positionsparameter
Einem Skript können Parameter übergeben werden, die man auch Positionsparameter nennt. Sie werden beim Aufruf des Skriptes mittels Variablen intern eingelesen. An erster Position steht $1, an zweiter $2, an dritter $3 und so weiter. Der Name des Skriptes steht in der Variable $0.
tux@deb12:~ $ nano kopiere
tux@deb12:~ $
tux@deb12:~ $ cat kopiere
#!/bin/bash
cp -a $1 $3
tux@deb12:~ $
tux@deb12:~ $ chmod +x kopiere
tux@deb12:~ $
tux@deb12:~ $ echo Hallo
Hallo
tux@deb12:~ $ echo INHALT > content.txt
tux@deb12:~ $
tux@deb12:~ $ # Der Hinweis zur Benutzung kommt, weil der dritte Übergabeparameter fehlt, der zweite aber nicht ausgewertet wird (sein Inhalt geht verloren):
tux@deb12:~ $ kopiere content.txt /tmp
Command line: cp -a content.txt
BusyBox v1.31.1 (2023-03-09 18:36:28 UTC) multi-call binary.
Usage: cp [OPTIONS] SOURCE... DEST
Copy SOURCE(s) to DEST
-a Same as -dpR
-R,-r Recurse
-d,-P Preserve symlinks (default if -R)
-L Follow all symlinks
-H Follow symlinks on command line
-p Preserve file attributes if possible
-f Overwrite
-i Prompt before overwrite
-l,-s Create (sym)links
-T Treat DEST as a normal file
-u Copy only newer files
tux@deb12:~ $
tux@deb12:~ $
tux@deb12:~ $ # Jetzt sind es 3 Parameter:
tux@deb12:~ $ kopiere content.txt nach /tmp
tux@deb12:~ $
tux@deb12:~ $ ls -l /tmp/content.txt
-rw-r--r-- 1 tux users 7 May 23 12:05 /tmp/content.txt
tux@deb12:~ $
Per Kommando read
axl@bookw:bin$ whatis read
read (2) - read from a file descriptor
axl@bookw:bin$
axl@bookw:bin$ help read
read: read [-ers] [-a Feld] [-d Begrenzer] [-i Text] [-n Zeichenanzahl] [-N Zeichenanzahl] [-p Prompt] [-t Zeitlimit] [-u fd] [Name ...]
Read a line from the standard input and split it into fields.
Reads a single line from the standard input, or from file descriptor FD
if the -u option is supplied. The line is split into fields as with word
splitting, and the first word is assigned to the first NAME, the second
word to the second NAME, and so on, with any leftover words assigned to
the last NAME. Only the characters found in $IFS are recognized as word
delimiters. By default, the backslash character escapes delimiter characters
and newline.
If no NAMEs are supplied, the line read is stored in the REPLY variable.
Options:
-a array assign the words read to sequential indices of the array
variable ARRAY, starting at zero
-d delim continue until the first character of DELIM is read, rather
than newline
-e use Readline to obtain the line
-i text use TEXT as the initial text for Readline
-n nchars return after reading NCHARS characters rather than waiting
for a newline, but honor a delimiter if fewer than
NCHARS characters are read before the delimiter
-N nchars return only after reading exactly NCHARS characters, unless
EOF is encountered or read times out, ignoring any
delimiter
-p prompt output the string PROMPT without a trailing newline before
attempting to read
-r do not allow backslashes to escape any characters
-s do not echo input coming from a terminal
-t timeout time out and return failure if a complete line of
input is not read within TIMEOUT seconds. The value of the
TMOUT variable is the default timeout. TIMEOUT may be a
fractional number. If TIMEOUT is 0, read returns
immediately, without trying to read any data, returning
success only if input is available on the specified
file descriptor. The exit status is greater than 128
if the timeout is exceeded
-u fd read from file descriptor FD instead of the standard input
Exit Status:
The return code is zero, unless end-of-file is encountered, read times out
(in which case it's greater than 128), a variable assignment error occurs,
or an invalid file descriptor is supplied as the argument to -u.
axl@bookw:bin$
axl@bookw:bin$
axl@bookw:bin$ read -p "Passwort eingeben: " -s
Passwort eingeben: axl@bookw:bin$
axl@bookw:bin$
axl@bookw:bin$ echo $REPLY
1234567
axl@bookw:bin$
axl@bookw:bin$
axl@bookw:bin$ read a b c
Wert1 Wert2 Wert3 Wert4 Wert5
axl@bookw:bin$
axl@bookw:bin$ echo $a
Wert1
axl@bookw:bin$
axl@bookw:bin$ echo $b
Wert2
axl@bookw:bin$
axl@bookw:bin$ echo $c
Wert3 Wert4 Wert5
axl@bookw:bin$
axl@bookw:bin$ # 'read' vergisst nichts: die letzte Variable beinhaltet den Rest!
Kontrollstrukturen
Richtig spannend wird es nun mit Hilfe einer Ablaufsteuerung, die auf Ereignisse reagieren kann.
Bedingte Ausführung
Die erste Art der Ablaufsteuerung beschränkt sich auf einfache Erfolgsprüfung.
Nur bei Erfolg: mit
&&werden Kommandozeilen verkettet, wobei nur weitergearbeitet wird, wenn die vorherige Zeile keinen Fehler brachte.Nur im Fehlerfall: mit
||werden Kommandozeilen verkettet, wobei nur weitergearbeitet wird, wenn die vorherige Zeile einen Fehler verursachte.Mit
||werden Kommandozeilen verkettet, wobei nur weitergearbeitet wird, wenn die vorherige Zeile Erfolg hat.
tux@deb12:~/bin$ test -u /usr/bin/passwd && echo "Datei hat das SUID-Bit." || echo "Datei hat das SUID-BIT nicht."
Datei hat das SUID-Bit.
tux@deb12:~/bin$
tux@deb12:~/bin$ test -u /usr/bin/date && echo "Datei hat das SUID-Bit." || echo "Datei hat das SUID-BIT nicht."
Datei hat das SUID-BIT nicht.
tux@deb12:~/bin$
Konstrukte zur Ablaufsteuerung
Jetzt wird es komplexer, mit den folgenden Konstrukten lassen sich umfangreiche Programme schreiben.
Es gibt Verzweigungen:
if-then-else-fi
case in …;; esac
und Schleifen:
for-in-do-done (Zählschleife, über eine Menge von Elementen gleiten…)
while–do-down (kleine Services schreiben, Überwachungsaufgaben)
select …; done (eine Sonderform, die zur Menübildung eingesetzt werden kann)
Verzweigungen:
Die if-Verzweigung ist die universellste. Hier ein einfaches Beispiel, wobei zur Entscheidungfindung das weiter unten beschriebene Kommando
testverwendet wird; zu besseren Lesbarkeit wird gern die Form mittels eckiger Klammern benutzt, wobei nach der öffnenden und vor der schließenden eckigen Klammer ein Leerzeichen stehen muss:if [ -f /etc/hosts ] then echo "Ja, es ist eine Datei, die vorhanden ist." else echo "Sorry, Objekt nicht gefunden oder keine Datei!" ls -l /etc/hosts fi
Das Kommando ’test vergleicht im nächsten Beispiel, ob die Zahl 1 kleiner als die Zahl 2 (lt = less then):
if [ 6 -lt 7 ] then echo "Passt." else echo "Passt nicht!" fi
Die case-Verzweigung ist speziell für den Mustervergleich gedacht. Im folgenden Beispiel eines Grundgerüstes für eine iptables-Firewall werden zwei Funktionen definiert, die in dann im Kommandoblock der Verzweigung aufgerufen werden. Damit das Skript nicht mit root-Rechten getestet werden muss, wurde dem Kommando bei der Variablen-Deklaration in Zeile 2 ein
echovorangestellt:#!/bin/bash fwcmd="echo /sbin/iptables" close(){ $fwcmd -P INPUT DROP $fwcmd -P FORWARD DROP $fwcmd -P OUTPUT DROP $fwcmd -A INPUT -i lo -j ACCEPT $fwcmd -A OUTPUT -o lo -j ACCEPT } open(){ $fwcmd -P INPUT ACCEPT $fwcmd -P FORWARD ACCEPT $fwcmd -P OUTPUT ACCEPT $fwcmd -F $fwcmd -Z } case "$1" in close|c) close ;; open|o) open ;; status|s) $fwcmd -vnL ;; *) echo "AUFRUF: $0 {close|open|status}" ;; esac
Schleifen:
Die for-Schleife, auch Zählschleife genannt, untersucht im folgenden Beispiel alle Dateien unter /etc, die mit “host” beginnen, hinsichtlich ihres Dateityps:
for i in /etc/host* do file $i sleep 2 doneDie while-Schleife des folgenden Beispiels läuft erst los, wenn ein Prozess gefunden wird. Nach dem Eingeben von
sleep 3mkann sie getestet werden. Die Bedingung, dass ein sleep-Prozess gefunden wird, realisiert die Zeilepgrep $prozess > /dev/null, die in eine Kommandozeilensubstitution eingebettet ist. Die Entscheidung trifft die Shell ohne weitere Hilfswerkzeuge allein aufgrund des Exit-Codes vonpgrep:prozess="sleep" while $(pgrep $prozess > /dev/null) do echo Prozess gefunden... sleep 3 done
Hilfswerkzeuge
Neben den üblichen Textfiltern wie cat, head, tail, grep, sed, awk, sort und anderen Tools wie netcat, nmap, lsof, ss, tcpdump usw. gibt es speziell für die Programmierung erforderliche Werkzeuge. Davon sollen ein paar vorgestellt werden.
Kommando test
Fürs Testen auf verschiedene Dateitypen und -eigenschaften sowie für den
Vergleich von Zeichenketten und Zahlen ist test ein wichtiges
Werkzeug. Es wird gern zur Definition von Bedingungen in Verzweigungen
und Schleifen eingesetzt. Anstelle von test kann auch die
Klammerschreibweise mit [ ... ] verwendet werden, dabei müssen aber
nach der öffnenden eckigen Klammer und vor der schließenden eckigen
Klammer Leerzeichen gesetzt werden.
LPI-relevante Optonen für Dateitests:
-e = existent
-x = existent und eXecutable
Hier ein paar Beispiele:
tux@deb12:~/bin$ test -e /etc/vfstab ; echo $?
1
tux@deb12:~/bin$ # >>> Fehler
tux@deb12:~/bin$
tux@deb12:~/bin$ test -e /etc/fstab ; echo $?
0
tux@deb12:~/bin$ # >>> Erfolg
tux@deb12:~/bin$
tux@deb12:~/bin$ [ -x /etc/fstab ]; echo $?
1
tux@deb12:~/bin$ # >>> Fehler, d.h. die Datei mag zwar existieren, sie ist aber nicht eXecutable!
tux@deb12:~/bin$
tux@deb12:~/bin$
tux@deb12:~/bin$ [ -x /usr/bin/date ]; echo $?
0
tux@deb12:~/bin$ # >>> Erfolg, d.h. die Datei ist exististent UND auch eXecutable
tux@deb12:~/bin$
tux@deb12:~/bin$
tux@deb12:~/bin$
tux@deb12:~/bin$
tux@deb12:~/bin$ # Ein bissl wie if-then-else: mit "&&" wird nur weitergearbeitet, wenn die vorherige Zeile
tux@deb12:~/bin$ # erfolgreich war:
tux@deb12:~/bin$ test -g /usr/bin/wall && echo 'Ja, das "file" hat das SGID-Bit.'
tux@deb12:~/bin$
tux@deb12:~/bin$ ls -l /usr/bin/wall
-rwxr-xr-x 1 root tty 39224 23. Mär 2023 /usr/bin/wall
tux@deb12:~/bin$
tux@deb12:~/bin$ ls -l /usr/bin/write
-rwxr-sr-x 1 root tty 22848 23. Mär 2023 /usr/bin/write
tux@deb12:~/bin$
tux@deb12:~/bin$ test -g /usr/bin/wall && echo 'Ja, das "file" hat das SGID-Bit.'
tux@deb12:~/bin$ echo $?
1
tux@deb12:~/bin$ # >>> "1" bedeutet "Fehler"
tux@deb12:~/bin$
tux@deb12:~/bin$
tux@deb12:~/bin$ # Genau so mit if-then-else machbar: mit "||" wird nur weitergearbeitet, wenn die vorherige Zeile einen Fehler geliefert hat:
tux@deb12:~/bin$ test -g /usr/bin/wall || echo 'Ja, das "file" hat das SGID-Bit.'
Ja, das "file" hat das SGID-Bit.
tux@deb12:~/bin$ echo $?
0
tux@deb12:~/bin$
Kommando seq
Das Tool erleichtert die Erzeugung von Zahlenfolgen.
axl@bookw:bin$ seq 3
1
2
3
axl@bookw:bin$
axl@bookw:bin$ seq 2 6
2
3
4
5
6
axl@bookw:bin$
axl@bookw:bin$ seq 2 2 6
2
4
6
axl@bookw:bin$
axl@bookw:bin$
axl@bookw:bin$ seq 1 5 20
1
6
11
16
axl@bookw:bin$ # >>> LPI-relevante Frage: es wird addiert!
axl@bookw:bin$ # 1 + 5 = 6
axl@bookw:bin$ # 6 + 5 = 11
axl@bookw:bin$ # 11 + 5 = 16
axl@bookw:bin$
axl@bookw:bin$ seq 5 -0.5 2
5,0
4,5
4,0
3,5
3,0
2,5
2,0
axl@bookw:bin$
Kommando shift
Damit kann man die Liste der Postitionsparameter verschieben, sie vom Prinzip her von links nach rechts Stück für Stück abarbeiten.
axl@bookw:bin$ cat > shifttest
shift
echo $1
axl@bookw:bin$
axl@bookw:bin$ # >>> Strg - d zum Speichern
axl@bookw:bin$
axl@bookw:bin$ bash shifttest
axl@bookw:bin$ bash shifttest Par1
axl@bookw:bin$ bash shifttest Par1 Par2
Par2
axl@bookw:bin$ bash shifttest Par1 Par2 Par3
Par2
axl@bookw:bin$ bash shifttest Par1 Par2 Par3 Par4
Par2
axl@bookw:bin$
Jetzt wollen wir die Parameterliste gleich um drei Werte verschieden:
axl@bookw:bin$ vi shifttest
axl@bookw:bin$ cat shifttest
shift 3
echo $1
axl@bookw:bin$
axl@bookw:bin$ bash shifttest Par1 Par2 Par3 Par4 Par5
Par4
axl@bookw:bin$
axl@bookw:bin$ # >>> 'shift 3' überspringt die ersten drei Parameter
axl@bookw:bin$
axl@bookw:bin$
axl@bookw:bin$
axl@bookw:bin$ # In der Praxis oft in der Übergabe von zusammengesetzten Optionen benutzt:
axl@bookw:bin$ whatis getopt
getopt (1) - Befehlsoptionen auswerten (erweitert)
getopt (3) - Parse command-line options
axl@bookw:bin$
Siehe dazu https://davetang.org/muse/2023/01/31/bash-script-that-accepts-short-long-and-positional-arguments/
Kommando exit
Man kann dem Kommando einen eigenen Wert mit geben (z.B. exit 99),
so dass man in der aufrufenden Shell den Exit-Code des Skriptes
auswerten kann.
Kommando nohup
Das Kommando löst Prozesse vom aufrufenden Elternprozess ab. Möchte der
Admin z.B. ein länger andauerndes Update durchführen, kann er
nohup apt-get -y upgrade & ausführen und sich dann gefahrlos
ausloggen, ohne dass sich apt-get beendet.
Nützlich ist das Kommando auch, wenn ein zweites Skript unabhängig vom ersten, aus dem es gestartet wurde, weiterlaufen soll.
Arithmetik
Increments und Decrements in Schleifen
Mit folgenden Beispielen kann eine Zahlenreihe hochgezählt werden (Increment), soll abwärts gezählt werden, ersetzt man die Plus-Zeichen durch Minus-Zeichen (Decrement).
Die Ausdrücke mit den doppelten runden Klammern sind eine andere Schreibweise für die Verwendung des internen bash-Befehls ‘let’ Siehe dazu ‘man bash’, Suche nach ‘((’ durchführen.
x=$((x+1)) ; echo $x
let x++ ; echo $x
((x++)) ; echo $x
Aus performancetechnischen Gründen sollte das externe Kommando ‘expr’ nicht mehr eingesetzt werden:
x=$(expr $x + 1) ; echo $x
x=`expr $x + 1` ; echo $x
Beispiel Countdown-Zähler:
#!/bin/bash
x=$1
while [ $x -ge 1 ]
do
((x--))
echo $x
done
Kommando factor
Für Primzahlen gibt es das Kommando factor:
tux@deb12:~$ whatis factor
factor (1) - Zahlen in Faktoren zerlegen
tux@deb12:~$
tux@deb12:~$ factor 8
8: 2 2 2
tux@deb12:~$ factor 7
7: 7
tux@deb12:~$
tux@deb12:~$
Empfehlenswerte Seite zur Vertiefung der mathematischen Möglichkeiten der Bash: https://phoenixnap.com/kb/bash-math