Bash-Globbing: Wildcards und Extglob erklärt
Bash-Globbing erklärt: Die Shell erweitert Wildcards vor dem Befehl. Mit nullglob, dotglob, globstar und Extglob-Negation vermeiden Sie typische Fehler.
Was Bash-Globbing vor dem Start Ihres Befehls macht
Beim Bash-Globbing wandelt die Shell ein Muster wie *.log in eine sortierte Liste vorhandener Dateinamen um, bevor der Befehl startet. rm *.log übergibt rm niemals ein Muster. Bash liest das Verzeichnis ein, behält die passenden Namen, sortiert sie und startet dann rm, wobei jeder Name als separates Argument übergeben wird. Das Programm rm kann nicht erkennen, dass zuvor ein Muster verwendet wurde.
Fast alle überraschenden Eigenschaften des Globbings ergeben sich aus dieser Tatsache. Die Shell führt die Übereinstimmungsprüfung anhand der Dateien durch, die zu diesem Zeitpunkt vorhanden sind. Der Befehl sieht nur die fertige Liste. Der formale Begriff dafür ist Pfadnamenerweiterung. Globbing ist die gebräuchliche Bezeichnung. Beide Begriffe bedeuten dasselbe.
Einen kleinen Verzeichnisbaum zum Üben erstellen
Alle folgenden Beispiele arbeiten mit denselben Dateien. Erstellen Sie sie in einem temporären Verzeichnis. So befinden sich keine wichtigen Dateien in der Nähe, und die Bereinigung erfolgt mit einem einzigen Befehl.
lab=$(mktemp -d)
cd "$lab"
mkdir -p logs archive/2025 archive/2026
touch app.log app.log.1 app.log.2 app.log.10 error.log debug.LOG
touch notes.txt notes.md README 'weekly report.log'
touch .env .apprc
touch logs/nginx.log logs/nginx.log.1
touch archive/2025/dec.log archive/2026/jan.logmktemp -d erstellt ein neues Verzeichnis und gibt dessen Pfad zurück. $(...) speichert diesen Pfad in der Variable lab. Falls diese Syntax neu für Sie ist, erklärt wie die Befehlssubstitution die Ausgabe eines Befehls übernimmt die Details vollständig.
Prüfen Sie, was Sie erstellt haben, und ermitteln Sie Ihre Shell, da eine Anmerkung am Ende von der Version abhängt:
ls -a
bash --versionAlles hier funktioniert mit bash 4.0 und höher. Die Anmerkung zu globskipdots am Ende gilt für bash 5.2 und höher. Das ist die Version, mit der aktuelle Ubuntu- und Debian-Releases seit August 2026 ausgeliefert werden.
Der durchgehend verwendete Vorschau-Befehl ist printf '%s\n' PATTERN. Er gibt einen Treffer pro Zeile aus und ändert nichts auf dem Datenträger. Daher können Sie ihn gefahrlos mit jedem Muster ausführen, bei dem Sie unsicher sind.
Die drei Wildcards: Stern, Fragezeichen und eckige Klammern
*steht für eine beliebige Zeichenfolge, auch für eine leere.?steht für genau ein Zeichen.[...]steht für genau ein Zeichen aus der in den Klammern angegebenen Menge.
printf '%s\n' *.log
printf '%s\n' app.log.?
printf '%s\n' app.log.[0-9]
printf '%s\n' notes.*
printf '%s\n' *Vergleichen Sie die zweite Zeile mit der von Ihnen erstellten Dateiliste. ? steht für genau ein Zeichen und für nichts Weiteres. Daher passt ein zweistelliges Suffix nicht zu diesem Muster. Erweitern Sie es zu app.log.[0-9]* und führen Sie den Befehl erneut aus, um den Unterschied zu sehen.
Für alle drei Wildcards gelten zwei Regeln. Kein Wildcard passt jemals auf ein /. Daher bleibt ein Muster auf eine Verzeichnisebene beschränkt. Ein führendes . muss wörtlich eingegeben werden. Ein Muster, das mit * beginnt, überspringt daher alle versteckten Namen. Aus diesem Grund lässt rm * Ihre Dotfiles unverändert.
Die Ergebnisse von Globs werden sortiert ausgegeben. Dabei wird die Sortierreihenfolge der aktuellen Locale verwendet, also eine zeichenweise Textsortierung. Ein Suffix aus 10 wird daher vor einem Suffix aus 2 sortiert, weil beim Vergleich keines der beiden als Zahl interpretiert wird. Führen Sie printf '%s\n' app.log.* und anschließend ls -v app.log.* aus und vergleichen Sie die Ergebnisse: ls -v sortiert eingebettete Zahlen nach ihrem Zahlenwert, und sort -V erledigt dasselbe in einer Pipeline.
Zeichenklassen und Bereiche
Innerhalb der eckigen Klammern können Sie eine Liste, einen Bereich oder eine Negation angeben.
[ch]entspricht einem Zeichen, entwedercoderh.[a-f]entspricht einem Zeichen aus dem Bereich von a bis f.[!0-9]entspricht einem Zeichen, das keine Ziffer ist.[^0-9]bedeutet dasselbe.
printf '%s\n' [dn]*
printf '%s\n' *.[A-Z]*
printf '%s\n' [A-Z]*Bereiche führen zu unterschiedlichen Ergebnissen auf verschiedenen Systemen. Ein Bereich wird anhand der Sortierreihenfolge der aktuellen Locale und nicht anhand von einfachem ASCII aufgelöst. Daher entspricht [a-z] auf manchen Systemen auch Großbuchstaben. Bash bietet eine Option globasciiranges, die die einfache ASCII-Reihenfolge erzwingt. In neueren Builds ist sie standardmäßig aktiviert. Prüfen Sie dies daher mit shopt globasciiranges, statt es anzunehmen. Ein Skript, das überall auf dieselbe Weise abgleichen muss, kann die Reihenfolge selbst festlegen, indem es LC_ALL=C in einer eigenen Zeile weiter oben im Skript setzt. Dadurch verwendet jeder Bereich wieder die einfache Byte-Reihenfolge.
Diese Zuweisung muss ein eigener Befehl sein. Als Präfix setzt LC_ALL=C ls [a-z]* die Locale nur für ls. Die Shell hat das Muster bereits in ihrer eigenen Locale erweitert, bevor ls überhaupt startet. Damit tritt wieder die Regel aus dem ersten Abschnitt in Kraft.
Brace-Expansion ist kein Globbing
Geschweifte Klammern sehen wie ein Platzhalter aus, verhalten sich aber völlig anders. Brace-Expansion wird deutlich früher als Globbing ausgeführt und greift niemals auf den Datenträger zu.
echo file{1,2,3}.txt
echo {01..10}
echo {a..e}
echo {0..20..5}Keine dieser Dateien existiert, und die Expansion wird trotzdem ausgeführt. Genau darin liegt der Unterschied: Ein Glob stellt dem Dateisystem eine Frage, während eine geschweifte Klammer lediglich Text erzeugt. Deshalb sind geschweifte Klammern das richtige Werkzeug zum Erstellen und nicht zum Suchen.
mkdir -p site/{css,js,img}
cp app.log{,.bak}
touch report-{2025,2026}-{01,02}.csvcp app.log{,.bak} wird in zwei Wörter expandiert: app.log und app.log.bak, weil das leere Element vor dem Komma den ursprünglichen Text reproduziert. {01..10} behält seine führenden Nullen, weil eine führende Null an einem der beiden Endpunkte dazu führt, dass bash jede erzeugte Zahl auf dieselbe Breite auffüllt.
Die Reihenfolge der Expansion erklärt außerdem einen häufigen Fehler. Bash expandiert zuerst geschweifte Klammern, danach Variablen und zuletzt Pfadnamen.
n=5
echo {1..$n}Die Brace-Expansion ist bereits abgeschlossen, wenn $n zu einer Zahl wird. Deshalb wird nie ein Bereich erzeugt. Verwenden Sie seq 1 "$n" oder eine Schleife im C-Stil, geschrieben als for ((i=1; i<=n; i++)).
Was passiert, wenn ein Muster keine Treffer liefert
Dies ist der erste Fehlerfall. Er tritt früher oder später bei jedem auf. Standardmäßig lässt bash ein Muster ohne Treffer vollständig unverändert. Das Wort wird genau so an den Befehl übergeben, wie Sie es eingegeben haben. Der Befehl erhält daher die Zeichen *, ., t, m und p und versucht, sie als Dateinamen zu verwenden.
printf '%s\n' *.tmpBei printf ist das unproblematisch. Bei einem Befehl, der Dateien oder andere Objekte erstellt, ist es das nicht. touch *.tmp erstellt in einem Verzeichnis ohne .tmp-Dateien eine Datei, deren Name tatsächlich *.tmp lautet. Zum anschließenden Löschen müssen Sie den Namen quoten, damit die Shell ihn nicht erneut expandiert: rm -- '*.tmp'.
Zwei Shell-Optionen ändern dieses Verhalten. Testen Sie jede Option mit einem Muster, das keine Treffer liefert, und deaktivieren Sie sie anschließend wieder.
shopt -s nullglob
printf '%s\n' *.tmp
shopt -u nullglob
shopt -s failglob
printf '%s\n' *.tmp
shopt -u failglobnullglob lässt ein Muster ohne Treffer zu einer leeren Zeichenfolge expandieren. Dadurch wird der Befehl mit weniger Argumenten ausgeführt, als Sie angegeben haben. Das ist in einer Schleife erwünscht. Bei deaktiviertem nullglob führt for f in *.tmp den Schleifenkörper einmal aus. f enthält dabei das wörtliche Muster. Das ist in fast jedem Skript, das so vorgeht, ein Fehler. Bei aktiviertem nullglob wird der Schleifenkörper kein einziges Mal ausgeführt.
nullglob birgt eine eigene Gefahr. Ein Befehl, dem alle Argumente entzogen wurden, wird trotzdem ausgeführt. ls *.nope wird zu einem allein stehenden ls. Dadurch wird das gesamte Verzeichnis aufgelistet. grep -l needle *.nope wird zu grep -l needle. Da keine Datei eingelesen werden kann, wartet der Befehl auf der Standardeingabe und wirkt, als wäre er eingefroren. Aktivieren Sie nullglob nur für die benötigte Schleife und deaktivieren Sie die Option danach wieder.
failglob verfolgt den anderen Ansatz: Ein Muster ohne Treffer gilt als Fehler. bash meldet den Fehler, und der Befehl wird überhaupt nicht ausgeführt. Für eine interaktive Shell ist das eine gute Einstellung. Sie verhindert, dass ein falsch eingegebenes Muster als wörtlicher Name an rm übergeben wird.
Versteckte Dateien: dotglob
shopt -s dotglob
printf '%s\n' *
shopt -u dotglobFühren Sie diesen Block aus und vergleichen Sie die Auflistung mit dem einfachen printf '%s\n' * von zuvor. dotglob entfernt die Regel für den führenden Punkt, sodass * auch Namen versteckter Dateien berücksichtigt. Die Einträge . und .. bleiben unter dotglob immer ausgeschlossen.
Ohne dotglob ist .* die übliche Methode, um versteckte Dateien zu erreichen, und sie war früher gefährlich. Unter bash-Versionen vor 5.2 erfasste .* außerdem . und .., sodass ein rekursiver Befehl wie chmod -R 755 .* direkt in das übergeordnete Verzeichnis lief. Bash 5.2 führte die Option globskipdots ein, die standardmäßig aktiviert ist und . sowie .. aus jeder Expansion heraushält. Führen Sie vorher shopt globskipdots aus, bevor Sie sich darauf verlassen, da diese Option auf einem älteren System nicht verfügbar ist.
globstar: rekursives Matching über den gesamten Verzeichnisbaum
shopt -s globstar
printf '%s\n' **/*.log
printf '%s\n' **/
shopt -u globstarWenn globstar gesetzt ist, passt ein **, das eine vollständige Pfadkomponente bildet, auf Dateien und Verzeichnisse in jeder Verzeichnistiefe, einschließlich null Ebenen. Damit umfasst **/*.log sowohl das aktuelle Verzeichnis als auch logs/ und alles unter archive/. Ein **/ mit abschließendem Schrägstrich passt nur auf Verzeichnisse. Dadurch lässt sich die Struktur eines Verzeichnisbaums schnell anzeigen.
Wenn globstar nicht gesetzt ist, verhält sich ** wie ein gewöhnliches * und bleibt in einem Verzeichnis. Führen Sie dasselbe Muster mit deaktivierter Option aus und vergleichen Sie die Ergebnisse. Ein rekursives Muster, das Sie von anderer Stelle übernommen haben und das deutlich weniger Ergebnisse liefert als erwartet, ist meistens darauf zurückzuführen. globstar ist in jeder bash standardmäßig deaktiviert.
Eine Einschränkung sollten Sie kennen: ** folgt keinen symbolischen Links auf Verzeichnisse. Für einen Verzeichnisbaum, der über symbolische Links verbunden ist, benötigen Sie stattdessen find -L.
nocaseglob für Dateinamen mit abweichender Groß- und Kleinschreibung
shopt -s nocaseglob
printf '%s\n' *.log
shopt -u nocaseglobnocaseglob sorgt dafür, dass der Abgleich von Dateinamen die Groß- und Kleinschreibung ignoriert. Dadurch passt beispielsweise ein Suffix .LOG in Großschreibung auf ein Muster .log in Kleinschreibung. Vergleichen Sie diese Ausgabe mit der Ausgabe aus dem ersten Abschnitt. Deaktivieren Sie die Option anschließend sofort wieder. Wenn sie aktiviert bleibt, ändert sie den Abgleich für jeden folgenden Befehl in dieser Shell. Das ist später nur schwer zu diagnostizieren.
nocaseglob gilt ausschließlich für die Dateinamenerweiterung. Die entsprechende Option für den Musterabgleich innerhalb einer case-Anweisung oder eines Tests mit doppelten eckigen Klammern ist nocasematch. Beide Optionen werden unabhängig voneinander gesetzt.
extglob: Muster für „nicht dieses“
Erweiterte Muster sind standardmäßig deaktiviert. Aktivieren Sie sie in einer eigenen Zeile:
shopt -s extglobEs gibt fünf Formen. Jede nimmt eine durch | getrennte Liste von Mustern entgegen:
?(list)findet kein oder ein Vorkommen.*(list)findet kein oder mehrere Vorkommen.+(list)findet ein oder mehrere Vorkommen.@(list)findet genau eine der Alternativen.!(list)findet alles, was zu keiner Alternative passt.
Ein erweitertes Muster muss von einer Shell verarbeitet werden, in der die Option bereits aktiviert ist. Deshalb steht der folgende Block in einem kleinen Skript, das mit bash -O extglob gestartet wird. Das Flag -O setzt eine shopt-Option, bevor die neue Shell die erste Zeile der Datei liest. Dadurch wird jedes Muster korrekt geparst. Der letzte Absatz dieses Abschnitts erklärt, warum die Reihenfolge wichtig ist.
cat > patterns.sh <<'EOF'
printf '%s\n' @(app|error).log
printf '%s\n' app.log.+([0-9])
printf '%s\n' *.@(md|txt)
printf '%s\n' !(*.log)
printf '%s\n' !(*.log|*.md|README)
EOF
bash -O extglob patterns.sh+([0-9]) bedeutet eine oder mehrere Ziffern. Damit werden nummerierte Suffixe beliebiger Länge abgedeckt. Das behebt die zuvor beschriebene Beschränkung von ?. Führen Sie beide Muster direkt nacheinander aus, um den Unterschied zu sehen.
Die Negationsform ist die Lösung für „alles außer“. Genau deshalb wird extglob überhaupt aktiviert. Dabei gibt es zwei Punkte, die viele Anwender überraschen.
Sie findet auch Verzeichnisse und nicht nur Dateien. Deshalb listet ls !(*.log) den Inhalt eines gefundenen Verzeichnisses auf, statt den Verzeichnisnamen auszugeben. Verwenden Sie ls -d oder die Vorschau printf, um die Namen selbst anzuzeigen.
Außerdem gilt wie bei jedem anderen Glob die Punktregel. !(*.log) findet daher jeden sichtbaren Namen, der nicht mit .log endet. Für versteckte Namen muss zusätzlich dotglob gesetzt werden.
Das ! in !(...) ist eine Glob-Negation. Es steht in keinem Zusammenhang mit History Expansion und dem Ausrufezeichen, einer separaten Funktion, die in einer anderen Phase ausgeführt wird.
Es gibt noch eine weitere Falle. Sie tritt beim Parsen auf. Bash parst einen vollständigen Befehl, bevor irgendein Teil davon ausgeführt wird. Deshalb schlägt es fehl, extglob zu aktivieren und ein erweitertes Muster in derselben Zeile zu verwenden: Das Muster wird geparst, während die Option noch deaktiviert ist. Setzen Sie shopt -s extglob in eine eigene Zeile, vor die Muster und möglichst weit oben im Skript. Der Rumpf einer Funktion wird geparst, wenn die Funktion definiert wird. Daher muss die Option vor der Definition und nicht erst vor dem Aufruf aktiviert werden. Wenn Sie die Shell mit bash -O extglob starten, wie im obigen Block, ist die Reihenfolge bereits vor Beginn des Parsens festgelegt.
Die Shell expandiert das Muster, der Befehl nicht
Dies ist der zweite Fehlermodus. Er erklärt eine ganze Gruppe von Fehlern.
grep -l needle *.log
find . -name '*.log'
find . -name *.logIn der ersten Zeile übernimmt bash die Übereinstimmungssuche, und grep erhält eine Liste von Dateinamen. In der zweiten Zeile wird das Muster in Anführungszeichen gesetzt. Dadurch erhält find die fünf Zeichen *.log und führt die Suche selbst aus, in jeder Verzeichnistiefe unterhalb des Startpunkts. Die dritte Zeile enthält den Fehler: bash expandiert das Muster zuerst, aber nur anhand des aktuellen Verzeichnisses. Dadurch wird find angewiesen, nach genau einem Namen zu suchen. In einem Verzeichnis mit genau einer Übereinstimmung sucht der Befehl stillschweigend nach dem falschen Objekt. Bei zwei oder mehr Übereinstimmungen meldet find einen Syntaxfehler, weil die zusätzlichen Namen an der Stelle ankommen, an der find einen Ausdruck erwartet.
Die Regel ist kurz. Ist das Muster für den Befehl bestimmt, setzen Sie es in Anführungszeichen. Ist es für die Shell bestimmt, lassen Sie es unverändert. Dieselbe Unterscheidung gilt für --exclude-Muster in tar und rsync sowie für die --include-Filter in grep.
Globs sind außerdem keine regulären Ausdrücke, auch wenn sie Zeichen gemeinsam verwenden. In einem Glob steht * für eine beliebige Folge von Zeichen. In einem regulären Ausdruck steht * für null oder mehr Vorkommen des jeweils vorhergehenden Elements. Daher sucht grep '*.log' nach etwas völlig anderem, als es auf den ersten Blick scheint.
Variablen folgen derselben Reihenfolge der Verarbeitungsschritte. Globbing läuft nach der Variablenexpansion. Eine nicht in Anführungszeichen gesetzte Variable, die ein Muster enthält, wird daher anhand des Verzeichnisses expandiert.
pat='*.log'
printf '%s\n' $pat
printf '%s\n' "$pat"Ohne Anführungszeichen führt bash Globbing auf dem Ergebnis der Variablen aus. Mit Anführungszeichen bleibt das Muster wörtlich erhalten. Eine damit verbundene Konsequenz sollten Sie beachten: Die durch Globbing erzeugten Wörter werden nicht erneut an Leerzeichen getrennt. Daher behandelt for f in *.log einen Dateinamen mit einem Leerzeichen als einen Namen, während for f in $(ls *.log) diesen Namen in zwei Wörter aufteilt. Durchlaufen Sie das Glob direkt.
Vorschau auf ein destruktives Muster, bevor Sie es ausführen
Verwenden Sie rm niemals als ersten Befehl für ein neues Muster. Führen Sie das Muster zunächst mit einem harmlosen Befehl aus, lesen Sie die Liste und ändern Sie anschließend nur den Befehl am Zeilenanfang.
target='!(*.log)'
printf '%s\n' $target
ls -ld -- $target
rm -- $targetWenn Sie das Muster einmal in target schreiben, können die drei Zeilen nicht mehr voneinander abweichen. $target bleibt absichtlich ohne Anführungszeichen, weil bash es dadurch expandieren kann. printf '%s\n' gibt einen Namen pro Zeile aus und verändert nichts. ls -ld zeigt jeden Eintrag selbst an, statt den Inhalt von Verzeichnissen aufzulisten. Die Modus-Spalte kennzeichnet, welche Einträge Verzeichnisse sind. Das müssen Sie vor jedem rekursiven Löschen prüfen. Die drwxr-xr-x-Berechtigungsbits lesen behandelt diese Spalte.
Rufen Sie die vorherige Zeile mit der Pfeil-nach-oben-Taste erneut auf und bearbeiten Sie nur den Befehl. Dadurch bleibt das Muster unverändert. Wenn Sie ein Muster aus dem Gedächtnis erneut eingeben, kann sich leicht ein Fehler einschleichen.
Setzen Sie -- vor das Muster. Damit wird das Ende der Optionen markiert. Ein Dateiname, der mit - beginnt, wird dadurch als Name und nicht als Flag behandelt.
Wenn Sie Globbing für einen Abschnitt eines Scripts deaktivieren möchten, schaltet set -f es aus und set +f es wieder ein.
Diese Vorgehensweise ist wichtig, weil rm keine Rückgängig-Funktion hat. Mit rm -rf gelöschte Dateien wiederherstellen ist langsam und meist unvollständig. Eine Vorschau kostet daher deutlich weniger als die Alternative.
Räumen Sie das Übungsverzeichnis auf, wenn Sie fertig sind. Geben Sie den Pfad aus und lesen Sie ihn zuerst. Ein auf die falsche Variable gerichtetes rm -rf verursacht genau den Unfall, um den es in diesem Abschnitt geht.
cd ~
echo "$lab"
rm -rf -- "$lab"FAQ
Warum findet find . -name *.log die falschen Dateien?
Weil bash *.log erweitert, bevor find überhaupt startet. Die Shell gleicht das Muster mit dem aktuellen Verzeichnis ab und übergibt den resultierenden Dateinamen an find. Dieses sucht dann auf jeder Verzeichnisebene nach genau diesem Namen. Wenn zwei oder mehr Dateien übereinstimmen, erhält find zusätzliche Argumente an der Stelle, an der ein Ausdruck erwartet wird, und meldet einen Syntaxfehler. Setzen Sie das Muster als find . -name '*.log' in Anführungszeichen. Dann führt find den Abgleich selbst durch, mit eigenen Regeln und eigener Rekursion.
Was bedeutet es, wenn mein Muster als literaler Text erscheint?
Das bedeutet, dass keine Übereinstimmung gefunden wurde. Standardmäßig lässt bash ein nicht übereinstimmendes Muster unverändert und übergibt die ursprünglichen Zeichen an den Befehl. Dieser behandelt sie dann als Dateinamen. Setzen Sie shopt -s failglob, damit ein nicht übereinstimmendes Muster einen Fehler erzeugt und den Befehl beendet. Alternativ können Sie shopt -s nullglob setzen, damit es zu nichts erweitert wird. Prüfen Sie bei nullglob, ob der Befehl auch ohne Argumente sinnvoll bleibt. Dann wird ls *.nope zu einem allein stehenden ls und listet das gesamte Verzeichnis auf.
Wie kann ich in bash jede Datei außer einem bestimmten Muster finden?
Aktivieren Sie erweiterte Muster mit shopt -s extglob in einer eigenen Zeile. Verwenden Sie anschließend die Negationsform. !(*.log) findet Namen, die nicht mit .log enden, und !(*.log|*.md) schließt beide aus. Verborgene Dateien bleiben aus dem Ergebnis ausgeschlossen, sofern nicht zusätzlich dotglob gesetzt ist. Verzeichnisse werden ebenfalls einbezogen. Prüfen Sie das Muster daher mit printf '%s\n' !(*.log), bevor Sie es an rm übergeben.
Warum überspringt * verborgene Dateien?
Ein führender Punkt muss wörtlich abgeglichen werden. Deshalb stimmt * nie mit einem Namen überein, der mit einem Punkt beginnt. Verwenden Sie .*, um verborgene Namen zu erfassen, oder setzen Sie shopt -s dotglob, damit sie in jedes gewöhnliche Muster einbezogen werden. Die Einträge . und .. bleiben bei dotglob immer ausgeschlossen. In bash 5.2 und später bleiben sie durch die Option globskipdots auch aus .* ausgeschlossen. Diese Option ist standardmäßig aktiviert.
Benötige ich globstar, damit ** funktioniert?
Ja. Ohne shopt -s globstar behandelt bash ** als gewöhnliches *. Dieses findet Übereinstimmungen innerhalb eines einzelnen Verzeichnisses und beendet die Suche dort. Mit aktiviertem globstar stimmt ein **, das eine vollständige Pfadkomponente bildet, auf jeder Verzeichnisebene überein. Dadurch erfasst **/*.log das aktuelle Verzeichnis und alle darunterliegenden Unterverzeichnisse. **/ allein findet dagegen nur Verzeichnisse. Beachten Sie, dass ** symbolischen Links auf Verzeichnisse nicht folgt. Verwenden Sie für einen aus symbolischen Links bestehenden Verzeichnisbaum find -L.