Pfade und Namen zerlegen — ganz ohne basename, dirname und sed
Die Shell kann Zeichenketten selbst zerschneiden. Kein Aufruf eines externen Programms, keine Pipe – nur geschweifte Klammern. Wenn du das einmal kennst, werden deine Skripte kürzer und deutlich schneller.
Ich habe jahrelang basename und dirname benutzt, ohne zu wissen, dass die Shell das selbst kann. In einer Schleife über tausend Dateien macht das einen spürbaren Unterschied: Jeder Aufruf startet einen eigenen Prozess. Die eingebaute Variante braucht keinen.
Die vier, die du dauernd brauchst
pfad="/var/www/kunde/bilder/logo.klein.png"
echo "${pfad##*/}" # logo.klein.png – alles bis zum letzten / weg
echo "${pfad%/*}" # /var/www/kunde/bilder – ab dem letzten / weg
echo "${pfad##*.}" # png – die Endung
echo "${pfad%.*}" # /var/www/kunde/bilder/logo.klein – Endung wegDie Logik dahinter ist simpel, wenn man sie einmal sieht:
#schneidet vorne ab,%schneidet hinten ab.- Einmal (
#,%) heißt kürzestmöglich, doppelt (##,%%) heißt längstmöglich.
Deshalb liefert ${pfad%.} bei logo.klein.png genau logo.klein — es wird nur die letzte Endung entfernt. ${pfad%%.} würde dagegen ab dem ersten Punkt kürzen und logo übrig lassen.
⚠️ Eine Falle, die du kennen solltest: Enthält die Zeichenkette gar kein /, dann gibt ${pfad%/*} den kompletten Wert zurück, nicht etwa . wie bei dirname. Bei blanken Dateinamen also lieber vorher prüfen.
Vorgabewerte statt if-Kaskaden
ziel="${1:-./build}" # erstes Argument, sonst ./build
echo "Baue nach $ziel"
: "${API_TOKEN:?API_TOKEN fehlt – bitte in der Umgebung setzen}"Die erste Zeile ersetzt drei Zeilen if. Die zweite bricht das Skript mit einer verständlichen Meldung ab, wenn die Variable fehlt oder leer ist — genau das, was man bei Zugangsdaten will, statt später einen kryptischen Fehler aus dem Programm zu bekommen. Das : davor ist der Nichts-tu-Befehl; er wertet nur die Erweiterung aus.
Ersetzen und zählen
name="Mein Kunden Projekt"
echo "${name// /-}" # Mein-Kunden-Projekt – alle Treffer
echo "${name/ /-}" # Mein-Kunden Projekt – nur der erste
echo "${#name}" # 19 – Länge
echo "${name,,}" # mein kunden projekt – klein
echo "${name^^}" # MEIN KUNDEN PROJEKT – groß${name,,} und ${name^^} brauchen Bash 4 oder neuer. Auf einem aktuellen Linux ist das kein Thema; auf dem alten macOS-Bash (3.2) fehlt es — dort hilft tr '[:upper:]' '[:lower:]'.
Ein Beispiel, das ich wirklich benutze
Bilder für den Web-Einsatz umwandeln und dabei den Namen behalten:
#!/usr/bin/env bash
set -euo pipefail
for bild in bilder/*.{jpg,png}; do
[ -e "$bild" ] || continue # kein Treffer? Muster überspringen
datei="${bild##*/}" # kunde-logo.png
ohne="${datei%.*}" # kunde-logo
cwebp -quiet -q 82 "$bild" -o "web/${ohne}.webp"
echo "→ web/${ohne}.webp"
doneKein basename, kein sed, keine Subshell. Bei ein paar Dateien merkst du nichts — bei ein paar tausend schon.
Solche kleinen Skripte sind bei mir Alltag: Bilder aufbereiten, Backups wegräumen, Deployments anstoßen. Wenn du sowas für dein Projekt brauchst oder deine Website ohnehin mal jemand ansehen sollte, melde dich gern über bymw.de.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
Warum deine Zählvariable nach der Schleife wieder 0 ist – Prozess-Substitution in Bash
Ein Klassiker, der jeden einmal erwischt: Du zählst in einer while-Schleife hoch, und hinterher steht die Variable trotzdem auf 0. Schuld ist eine Subshell hinter der Pipe. Mit Prozess-Substitution behältst du das Ergebnis – und kannst nebenbei zwei Befehle direkt vergleichen.
getopts – Skript-Parameter, die sich wie richtige Befehle anfühlen
$1, $2, $3 funktioniert genau so lange, bis man einen Parameter weglassen will. Mit getopts bekommt dein Skript benannte Optionen, eine Hilfe und eine klare Fehlermeldung – in fünfzehn Zeilen.
Zwei Listen vergleichen mit comm – wer fehlt, wer ist neu, wer ist in beiden
Welche Dateien fehlen im Backup? Welche Kunden aus der alten Liste stehen nicht in der neuen? Für genau diese Fragen gibt es seit Unix-Urzeiten ein Werkzeug, das kaum jemand kennt – comm vergleicht zwei sortierte Listen und sagt dir in einer Zeile, was nur links, nur rechts oder in beiden steht.