Shell Skripte in Linux
(Mi)Shell :--))¶
Variablenschreibweisen¶
Allgemein zusammengeschrieben der Schlüssel, mit Anführungszeichen wenn Leerzeichen vorkommen der Wert
mein_name="Linux User"
echo $mein_name
Umgebungsvariablen für Unterprozesse¶
export VARIABLE=Wert
Befehlsausgabe speichern¶
datum=$(date)
echo "Heute ist $datum"
Exakte Eingrenzung¶
{} grenzen eine Variable genau ein, Beispiel:
echo "$DATEI_backup" - Sucht nach der Variablen DATEI_backup
echo "${DATEI}_backup" - nutz Variable DATEI und hängt _backup an!
Pfade und Endungen (Dateinamenerweiterung)¶
Annahme FILE="/home/user/bilder/urlaub.jpg"
Dateinamen extrahieren (wie basename):
${FILE##*/} -> urlaub.jpg - löscht alles bis zum letzten /
Pfad extrahieren (wie 'dirname'):
${FILE%/*} -> /home/user/bilder - löscht ab dem letzten /
Nur die Endung:
${FILE##*.} -> jpg - löscht alles bis zum letzten .
Dateiname ohne Endung:
NAME=${FILE##*/} gefolgt von ${NAME%.*} -> urlaub
Einfaches Suchen und Ersetzen¶
${VARIABLE/alt/neu} - Erstes Vorkommen von alt durch neu ersetzen
${VARIABLE//alt/neu} - Alle Vorkommen von alt durch neu ersetzen
Beispiel Endung ändern:
${FILE/.jpg/.png} -> /home/user/bilder/urlaub.png
Standardwerte setzen¶
${1:-Standardwert} - Wenn $1 leer ist, nimm "Standardwert"
Beispiel:
BACKUP_DIR=${DIR:-/tmp/backup} - Weise der Variablen DIR den Wert /tmp/backup zu
Case-Umwandlungen¶
${VAR^^}: Gesamter Inhalt in GROSSBUCHSTABEN
${VAR,,}: Gesamter Inhalt in kleinbuchstaben
${VAR^}: Erster Buchstabe groß
${VAR,}: Erster Buchstabe klein
${VAR~}: Umkehr, Groß -> klein, klein -> Groß
Sonstiger String Kram¶
${#VAR}: Stringlänge
Systemvariablen¶
In Linux gibt es eine Reihe von Umgebungsvariablen, die das System und deine Programme steuern. Du kannst sie jederzeit mit echo $VARIABLE abrufen.
ACHTUNG! Manche dieser Variablen funktionieren z.B. in CachyOS nicht unter fish, sondern nur in sh oder bash!
| Variable | Beschreibung | Beispiel / Details |
|---|---|---|
$USER |
Username | ${USER} |
$HOME |
Persönliches Verzeichnis | /home/nutzer oder /home/${USER} |
$PATH |
Suchpfad für Befehle | Liste von Ordnern, getrennt durch : |
$PWD |
Aktuelles Verzeichnis | print working directory |
$OLDPWD |
Vorheriges Verzeichnis | cd -, um dorthin zurückzuspringen |
$UID |
User-ID | 0 für root, 1000+ für User |
$SHELL |
Pfad zur aktuellen Shell | z. B. /bin/bash |
$HOSTNAME |
Netzwerkname des Rechners | Name des Systems |
$EDITOR |
Bevorzugter Texteditor | z. B. nano oder vim |
$LANG |
Sprache & Zeichenkodierung | z. B. de_DE.UTF-8 |
$TERM |
Typ des Terminal-Emulators | Steuert Farben/Tastatur |
$PS1 |
Aussehen der Eingabeaufforderung | Text links vom Cursor |
$RANDOM |
Zufallszahl | Bereich: 0 bis 32767 |
$SECONDS |
Laufzeit der Shell | Sekunden seit Sitzungsstart |
Kommandozeilenargumente¶
$0: Name des Skripts
$1: Das erste Argument
$2: Das zweite Argument
${10}: Ab dem zehnten Klammern nötig, Klammern grenzen übrigens auch exakt Variablen ein!
$#: Gesamtzahl der Argumente
$@: Behandelt jedes Argument als separates Objekt
$*: Behandelt alle Argumente zusammen als eine einzige Zeichenkette
Für's Parsen nimmt man getopts¶
#!/bin/bash
while getopts "n:v" opt; do
case $opt in
n) name=$OPTARG ;; # -n erwartet einen Wert ($OPTARG)
v) verbose=1 ;; # -v ist ein einfacher Schalter
*) echo "Ungültige Option" ;;
esac
done
echo "Hallo $name"
Weiteres Beispiel¶
while getopts "hf:" opt; do
case $opt in
h) echo "Hilfe-Text..." ;;
f) datei=$OPTARG ;; # $OPTARG enthält den Wert hinter -f
\?) echo "Fehler!" ;; # Wird bei unbekannten Optionen aufgerufen
esac
done
"hf:": welche Buchstaben sind erlaubt
h: Einfacher Schalter
f:: Erwartet ein Argument
Systemvariablen¶
$opt: der aktuelle Optionsbuchstabe
$OPTARG: Wert der zu einer Option gehört
$OPTIND: Index, zeigt auf nächste Position in der Argumentliste
Shiften¶
Mit shift löscht man die bereits verarbeiteten Optionen aus der Liste der Parameter:
# Nach der while-getopts-Schleife:
shift $((OPTIND - 1))
# Jetzt ist $1 das erste Argument NACH den Optionen
echo "Erstes freies Argument: $1"
Shelloptionen (shopt)¶
Dateisuche Case-Insensitive¶
Beispiel: man hat Dateien mit .iso, .ISO oder jegliche Kombination daraus
nocaseglob:
shopt -s nocaseglob # Einschalten
for file in *.iso; do
echo "Gefunden: $file"
# Hier kannst du jetzt z.B. alles in Kleinbuchstaben umbenennen:
# mv "$file" "${file,,}"
done
shopt -u nocaseglob # Wieder ausschalten (optional)
Ich hab ein Date ...¶
Klassiker für Zeitstempel¶
Für Dateinamen empfiehlt sich das Format Jahr-Monat-Tag, damit die Dateien im Explorer korrekt nach Namen sortiert werden:
ISO-Datum (JJJJ-MM-TT): $(date +%F) → 2024-05-20
Kompakter Zeitstempel: $(date +%Y%m%d_%H%M%S) → 20240520_143005
Eindeutiger Unix-Timestamp: $(date +%s) → 1716210005 (Sekunden seit 1970 – perfekt für absolut eindeutige IDs)
Einzelne Bausteine¶
%Y / %y: Jahr (2024 / 24)
%m: Monat (01..12)
%d: Tag (01..31)
%H: Stunde (00..23)
%M: Minute (00..59)
%S: Sekunde (00..59)
%N: Nanosekunden (wenn es extrem schnell gehen muss)
Variablen nutzen¶
TS=$(date +%Y%m%d_%H%M)
LOGFILE="log_$TS.txt"
BACKUP="data_$TS.tar.gz"
Schleifen¶
Drei Beispiele für Schleifen
Dateien umbenennen (Manipulation von Endungen)¶
Alle .jpeg ind .jpg:
for file in *.jpeg; do
# Den Dateinamen ohne Endung extrahieren
name="${file%.jpeg}"
# Umbenennen mit neuer Endung
mv "$file" "${name}.jpg"
echo "Umgewandelt: $file -> ${name}.jpg"
done
Backups mit Zeitstempel erstellen¶
Beispiel:
# Backupverzeichnis, ISO-Datum %F
BACKUP_DIR="./backup_$(date +%F)"
# Verzeichnis erstellen
mkdir -p "$BACKUP_DIR"
for path in /home/user/dokumente/*.txt; do
# Nur den Dateinamen ohne den Pfad nehmen
filename="${path##*/}"
# Zeitstempel inklusive Sekunden für Eindeutigkeit
timestamp=$(date +%H%M%S)
cp "$path" "$BACKUP_DIR/${timestamp}_$filename"
done
Argumente verarbeiten und prüfen (getopts)¶
Liste von Dateien verarbeiten, aber nur wenn eine bestimmte Option gesetzt ist:
# Wenn der Schalter -d gesetzt ist:
while getopts "d" opt; do
case $opt in
d) delete_mode=1 ;; # Lösch-Modus aktivieren
esac
done
shift $((OPTIND - 1)) # Optionen entfernen, nur Dateinamen behalten
for item in "$@"; do
if [ "$delete_mode" == "1" ]; then
echo "Lösche Datei: $item"
# rm "$item" - hier kommentiert, damit nicht wirklich gelöscht wird :-)
else
echo "Verarbeite Datei: ${item^^}" # ^^ macht den Text zu GROSSBUCHSTABEN
fi
done
Arrays¶
Zahlen-Range: for i in {1..5}; do touch "test_$i.log"; done
Erstellt die (leeren) Dateien test_1.log bis test_5.log
Inhaltsabhängig:
LISTE="Server1 Server2 Server3"
for s in $LISTE; do ping -c 1 "$s"; done
Pingt jeden Server aus
LISTE an
IF und Vergleiche¶
Ja/Nein Abfrage¶
read -p "Fortfahren? (y/n): " answer
if [[ $answer == [yY]* ]]; then
echo "Aktion wird ausgeführt..."
fi
[yY]*: Beginnt mit kleinem oder großen yY, gefolgt von beliebigem Text *
String-Vergleiche¶
Gleichheit: [[ $A == $B ]] oder [[ $A = $B ]]
Ungleichheit: [[ $A != $B ]]
Prüfen ob leer: [[ -z $VAR ]] - True, wenn Variable leer
Prüfen ob nicht leer: [[ -n $VAR ]] - True, wenn Variable nicht leer
Numerische Vergleiche¶
Für Zahlen nutzt man in [[ ... ]] spezielle Kürzel oder die doppelte runde Klammer (( ... )):
-eq: Gleichheit
-ne: Ungleichheit
-lt: (less than), kleiner als
-gt: (greater than), größer als
-le: (less or equal)
-ge: (greater or equal)
-nt: (newer than), Dateivergleich
Beispiel:
if [[ $ANZAHL -gt 10 ]]; then
echo "Das sind mehr als 10 Dateien!"
fi
Dateitests¶
Eigenschaften von Dateien und Ordnern prüfen:
-f: Datei existiert und ist eine reguläre Datei?
-d: Verzeichnis existiert?
-e: Pfad existiert? Egal ob Datei oder Ordner
-r / -w / -x: Datei les-, schreib-, ausführbar?
-s: Datei existiert und ist nicht leer
-L: Ist es ein symbolischer Link?
Beispiel:
if [[ -f "/etc/passwd" ]]; then
echo "Die Datei existiert."
fi
Verknüpfungen von Bedingungen¶
&& (UND): [[ $A == "ja" && $B -gt 5 ]] - Variable A is "ja" UND Variable B ist größer als 5
|| (ODER): [[ $A == "ja" || $A == "yes" ]] - Variable A ist entweder "ja" ODER "yes"
Script Snippets¶
Usage-Funktion¶
usage() {
echo "Benutzung: $0 [OPTION] DATEI"
echo " -v Verbose Modus"
echo " -h Diese Hilfe anzeigen"
exit 1
}
# Wenn keine Argumente übergeben wurden ($# ist Anzahl)
[[ $# -eq 0 ]] && usage
Farben, globale Variablen, etc.¶
# Farben (C_ für Color)
C_RED='\033[0;31m'
C_GRN='\033[0;32m'
C_YLW='\033[1;33m'
C_NC='\033[0m' # No Color / Reset
# Temporäre Sachen
TMPDIR=$(mktemp -d) # Ein ganzer Ordner
TMPFILE=$(mktemp) # Eine einzelne Datei
trap 'rm -rf "$TMPDIR" "$TMPFILE"' EXIT # Automatisches Aufräumen