Die nullglob
Option (bei der es sich übrigens um eine zsh
Erfindung handelt, die erst Jahre später zu bash
( 2.0
) hinzugefügt wurde ) wäre in einigen Fällen nicht ideal. Und ls
ist ein gutes Beispiel:
ls *.txt
Oder sein korrekteres Äquivalent:
ls -- *.txt
Mit nullglob
on würde ls
ohne Argument ausgeführt, das wie folgt behandelt wird ls -- .
(das aktuelle Verzeichnis auflisten), wenn keine Dateien übereinstimmen. Dies ist wahrscheinlich schlimmer als der Aufruf ls
mit einem Literal *.txt
als Argument.
Bei den meisten Textdienstprogrammen treten ähnliche Probleme auf:
grep foo *.txt
Würde foo
auf stdin suchen, wenn es keine txt
Datei gibt.
Eine vernünftigere Standardeinstellung, und zwar csh, tcsh, zsh oder fish 2.3+ (und frühere Unix-Shells), besteht darin, den Befehl insgesamt abzubrechen, wenn der Glob nicht übereinstimmt.
bash
(ab Version 3) eine failglob
Option für die (interessant für diese Diskussion, da im Gegensatz zu ash
AT & T ksh
oder zsh
, bash
nicht lokalen Bereichen für Optionen unterstützen (obwohl das in 4.4 zu ändern ist), diese Option , wenn aktivierte global ein paar Dinge nicht bricht wie die Bash-Completion-Funktionen).
Beachten Sie, dass csh und tcsh leicht unterschiedlich sind zsh
, fish
oder bash -O failglob
in Fällen wie:
ls -- *.txt *.html
Hier müssen alle Globs nicht übereinstimmen, damit der Befehl abgebrochen wird. Wenn es zum Beispiel eine TXT-Datei und keine HTML-Datei gibt, wird dies zu:
ls -- file.txt
Sie können dieses Verhalten bekommen zsh
mit , setopt cshnullglob
obwohl ein vernünftiger Weg , es zu tun in zsh
sein würde wie ein Klacks zu verwenden:
ls -- *.(txt|html)
In zsh
und ksh93
können Sie nullglob auch global anwenden. Dies ist weitaus vernünftiger als das Ändern einer globalen Einstellung:
files=(*.txt(N)) # zsh
files=(~(N)*.txt) # ksh93
würde ein leeres Array erstellen, wenn es keine txt
Datei gäbe, anstatt den Befehl mit einem Fehler fehlzuschlagen (oder es zu einem Array mit einem *.txt
Literalargument mit anderen Shells zu machen).
Versionen fish
vor 2.3 würden funktionieren bash -O nullglob
, geben aber eine Warnung aus, wenn sie interaktiv sind, wenn ein Glob keine Übereinstimmung hat. Seit 2.3, funktioniert es wie mit zsh
Ausnahme von Klümpchen verwendet in for
, set
oder count
.
In der Verlaufsnotiz wurde das Verhalten tatsächlich von der Bourne-Shell unterbrochen . In früheren Unix-Versionen wurde das Globbing über den /etc/glob
Helper ausgeführt, und dieser Helper verhielt sich wie csh
folgt: Der Befehl schlug fehl, wenn keiner der Globs mit einer Datei übereinstimmte, und entfernte die Globs, wenn keine andere Übereinstimmung bestand.
Die Situation, in der wir uns heute befinden, ist auf eine schlechte Entscheidung in der Bourne-Shell zurückzuführen.
Beachten Sie, dass die Bourne-Shell (und die C-Shell) eine weitere neue Unix-Funktion enthielten: die Umgebung. Das bedeutete variable Erweiterung (der Vorgänger hatte nur die $1
, $2
... Positionsparameter). Die Bourne-Shell führte auch die Befehlsersetzung ein.
Eine weitere schlechte Designentscheidung der Bourne-Shell war das Durchführen von Globbing (und Splitting) bei der Erweiterung von Variablen und der Befehlssubstitution (möglicherweise aus Gründen der Abwärtskompatibilität mit der Thompson-Shell, bei echo $1
der /etc/glob
bei Verwendung von $1
Platzhaltern immer noch aufgerufen wird) da wurde wie im expandierten wert nochmal als shell code geparst)).
Fehlgeschlagene Globs, die nicht übereinstimmen, bedeuten zum Beispiel Folgendes:
pattern='a.*b'
grep $pattern file
würde den Befehl nicht ausführen (es sei denn, a.whateverb
das aktuelle Verzeichnis enthält einige Dateien). csh
(das auch Globbing bei variabler Erweiterung ausführt) scheitert in diesem Fall am Befehl (und ich würde behaupten, es ist besser, als dort einen ruhenden Fehler zu hinterlassen, auch wenn es nicht so gut ist, als würde man überhaupt kein Globbing wie in ausführen zsh
).