Wer regelmäßig in der Shell arbeitet, braucht eine Möglichkeit, mehrere Dateien auf einmal anzusprechen — ohne jeden Dateinamen einzeln einzutippen. Genau dafür gibt es Globbing. Mit Wildcards wie *, ? oder [abc] beschreibst du Muster, die die Shell automatisch zu konkreten Dateinamen expandiert. Das ist schneller, präziser und weniger fehleranfällig als manuelle Listen.
In diesem Tutorial lernst du, wie Bash-Globbing funktioniert, welche Wildcards es gibt und wie du mit erweiterten Features wie extglob und globstar auch komplexe Dateistrukturen effizient durchsuchst. Am Ende kläre ich außerdem den häufig verwechselten Unterschied zwischen Globbing und regulären Ausdrücken.
Was ist Globbing?
Globbing bezeichnet die Mustererweiterung auf Shell-Ebene: Bevor Bash einen Befehl ausführt, ersetzt es Muster wie *.txt durch alle passenden Dateinamen im aktuellen Verzeichnis. Dieser Schritt heißt Pathname Expansion und ist fest in die Shell eingebaut — kein externes Tool ist dafür nötig.
Ein einfaches Beispiel: Du tippst ls *.log, und Bash expandiert das zu ls fehler.log zugriff.log debug.log, bevor ls überhaupt aufgerufen wird. Der Befehl selbst sieht nie das Muster, sondern nur die fertigen Dateinamen. Dieses Verhalten ist wichtig zu verstehen, weil es den Unterschied zu Regex-Tools wie grep erklärt — dazu mehr am Ende des Artikels.
Die wichtigsten Wildcards
Bash kennt mehrere Globbing-Zeichen, die sich in ihrer Reichweite unterscheiden. Hier ein Überblick:
| Wildcard | Bedeutung | Beispiel |
|---|---|---|
* | Beliebig viele (auch null) Zeichen | *.txt matcht alle .txt-Dateien |
? | Genau ein beliebiges Zeichen | foto?.jpg matcht foto1.jpg, fotoA.jpg |
[abc] | Eines der aufgelisteten Zeichen | [Dd]oku* matcht Doku… und doku… |
[a-z] | Ein Zeichen aus dem Bereich | datei[0-9].txt matcht datei0.txt bis datei9.txt |
[!abc] | Kein Zeichen aus der Liste | [!.]* matcht alles außer versteckten Dateien |
{a,b} | Brace Expansion: jede der Alternativen | {jpg,png,gif} expandiert zu drei Strings |
Ein paar konkrete Beispiele in der Praxis:
ls *.txt # alle .txt-Dateien im aktuellen Verzeichnis
ls foto?.jpg # foto1.jpg, fotoA.jpg, aber nicht foto10.jpg
ls [Dd]oku* # Doku-readme.md und doku-readme.md
cp bild{1,2,3}.png backup/ # kopiert bild1.png, bild2.png, bild3.png
Statt der [Dd]-Konstruktion kannst du mit shopt -s nocaseglob auch generell ohne Beachtung der Groß-/Kleinschreibung matchen — dann findet ls doku* ebenso Doku-readme.md.
Ein wichtiger Hinweis zu {a,b}: Das ist technisch gesehen keine Pathname Expansion, sondern Brace Expansion — Bash expandiert die geschweiften Klammern unabhängig davon, ob die Dateien existieren. Das macht sie nützlich zum Erstellen von Dateistrukturen:
mkdir -p projekt/{src,tests,docs}
# erstellt drei Unterverzeichnisse auf einmal
Erweitertes Globbing (extglob)
Standardmäßig sind die Möglichkeiten von Globbing begrenzt. Mit shopt -s extglob aktivierst du erweiterte Muster, die deutlich mächtiger sind:
shopt -s extglob
Damit stehen fünf neue Operatoren zur Verfügung:
| Operator | Bedeutung |
|---|---|
!(muster) | Alles außer diesem Muster |
*(muster) | Null oder mehr Wiederholungen |
+(muster) | Eine oder mehr Wiederholungen |
?(muster) | Null oder eine Wiederholung |
@(muster) | Genau eine Übereinstimmung |
Praktisches Beispiel: Du willst alle Dateien außer .log-Dateien anzeigen:
shopt -s extglob
ls !(*.log)
# zeigt alle Dateien außer den .log-Dateien
Oder du willst — typisch in der Web-Entwicklung — alle Bilddateien unabhängig vom Format auflisten:
shopt -s extglob
ls @(*.jpg|*.jpeg|*.png|*.webp)
# zeigt alle Bilder im Verzeichnis, egal in welchem Format
extglob ist dauerhaft aktiv bis zum Ende der Shell-Session, kann aber auch in .bashrc gesetzt werden, wenn du es permanent möchtest.
Globbing gezielt verhindern
Manchmal ist Globbing nicht erwünscht. Sobald ein Muster in einer Variablen steckt, entscheidet die Anführungszeichen-Verwendung darüber, ob die Shell es expandiert oder als wörtlichen String behandelt:
pattern="*.txt"
rm $pattern # expandiert sofort zu allen .txt-Dateien
rm "$pattern" # übergibt den Literal-String "*.txt" an rm
Die unquotierte Variante löscht im Zweifel mehr als beabsichtigt — gerade in Skripten ein gefährlicher Stolperstein. Als Faustregel: Variablen, die kein Glob auslösen sollen, immer in doppelte Anführungszeichen setzen.
Wer Globbing für einen ganzen Skriptabschnitt abschalten will, nutzt set -f (gleichbedeutend mit set -o noglob). Danach werden *, ? und […] nicht mehr expandiert, bis du es mit set +f wieder einschaltest. Das ist defensives Wissen für Skripte, die mit Mustern als Daten arbeiten:
set -f # Globbing aus
set +f # Globbing wieder an
Globstar: rekursiv mit **
Normalerweise matcht * keine Verzeichnistrennzeichen — *.js findet also nur .js-Dateien im aktuellen Verzeichnis, nicht in Unterordnern. Mit globstar ändert sich das:
shopt -s globstar
ls **/*.js
# findet alle .js-Dateien im aktuellen Verzeichnis und allen Unterverzeichnissen
** allein steht dabei für "aktuelles Verzeichnis und alle Unterverzeichnisse rekursiv". Das ist besonders nützlich in Kombination mit anderen Befehlen:
shopt -s globstar
# alle TypeScript-Dateien kompilieren
tsc **/*.ts
# alle Markdown-Dateien finden
echo **/*.md
# alle Logdateien eines Projekts auf einmal löschen
rm logs/**/*.log
Auch globstar kann in .bashrc permanent aktiviert werden. In neueren Bash-Versionen (ab 4.0) ist es verfügbar, aber nicht standardmäßig eingeschaltet.
nullglob & dotglob
Zwei weitere Shell-Optionen, die das Verhalten von Globbing beeinflussen:
nullglob — Was passiert, wenn ein Muster keine Datei matcht? Standardmäßig gibt Bash das Muster unverändert zurück, was zu unerwarteten Fehlern führen kann:
# ohne nullglob: rm bekommt den String "*.tmp" als Argument
rm *.tmp
# Fehler: rm: cannot remove '*.tmp': No such file or directory
shopt -s nullglob
rm *.tmp
# Kein Fehler: Das Muster expandiert zu nichts, rm wird ohne Argumente aufgerufen
Mit nullglob expandiert ein nicht-matchendes Muster zu einer leeren Liste statt zum Muster selbst — sicherer in Skripten.
dotglob — Versteckte Dateien (Dateien, die mit . beginnen) werden von Globbing standardmäßig ignoriert. Mit dotglob werden sie eingeschlossen:
shopt -s dotglob
ls *
# zeigt jetzt auch .bashrc, .gitignore, .env usw.
# nützlich, um ein Verzeichnis inklusive versteckter Dateien zu kopieren:
shopt -s dotglob
cp quelle/* ziel/
Beide Optionen lassen sich mit shopt -u wieder deaktivieren.
Unterschied Globbing vs. Regex
Globbing expandiert Dateinamen auf Shell-Ebene, Regex matcht Text in Tools wie grep oder sed. Das ist der grundlegende Unterschied, der oft für Verwirrung sorgt.
Konkret: Wenn du ls *.txt eingibst, ist das Globbing — Bash ersetzt *.txt durch Dateinamen. Wenn du grep 'fehler.*zeile' logfile.txt verwendest, ist das Regex — grep durchsucht den Dateiinhalt nach dem Muster.
Die Syntax sieht ähnlich aus, bedeutet aber etwas anderes:
| Zeichen | Glob-Bedeutung | Regex-Bedeutung |
|---|---|---|
* | Beliebig viele beliebige Zeichen | Wiederholung des vorherigen Zeichens (0 oder mehr) |
? | Genau ein beliebiges Zeichen | Vorheriges Zeichen optional (0 oder 1 mal) |
. | Literal-Punkt | Beliebiges einzelnes Zeichen |
[abc] | Eines dieser Zeichen | Eines dieser Zeichen (gleiche Bedeutung) |
Ein häufiger Fehler: grep "*.log" logfile.txt tut nicht das, was man erwartet. In Regex bedeutet * "null oder mehr vom vorherigen Zeichen", nicht "beliebige Zeichen". Korrekt wäre grep ".*\.log" logfile.txt.
Für eine ausführliche Einführung in reguläre Ausdrücke empfehle ich das Regex-Tutorial — dort findest du Syntax, Quantoren und praktische Anwendungsfälle.
Fazit
Globbing ist eines der wichtigsten Werkzeuge für produktives Arbeiten in der Shell. Mit den Basis-Wildcards *, ? und […] deckst du die meisten Alltagsaufgaben ab. Für komplexere Szenarien liefern extglob, globstar, nullglob und dotglob die nötige Flexibilität — sie müssen nur einmalig aktiviert werden.
Der wichtigste Merksatz: Globbing arbeitet auf Dateinamen, Regex auf Textinhalt. Diese Trennung sauber im Kopf zu haben, verhindert viele Shell-Bugs.
Wenn du tiefer einsteigen möchtest, sammelt der Shell-Scripting-Hub weiterführende Tutorials — vom Unterschied zwischen Bash, Zsh und Fish bis zu den Grundlagen regulärer Ausdrücke, die hier nur kurz angerissen wurden.
