Die nullglobOption (bei der es sich übrigens um eine zshErfindung handelt, die erst Jahre später zu bash( 2.0) hinzugefügt wurde ) wäre in einigen Fällen nicht ideal. Und lsist ein gutes Beispiel:
ls *.txt
Oder sein korrekteres Äquivalent:
ls -- *.txt
Mit nullglobon würde lsohne Argument ausgeführt, das wie folgt behandelt wird ls -- .(das aktuelle Verzeichnis auflisten), wenn keine Dateien übereinstimmen. Dies ist wahrscheinlich schlimmer als der Aufruf lsmit einem Literal *.txtals Argument.
Bei den meisten Textdienstprogrammen treten ähnliche Probleme auf:
grep foo *.txt
Würde fooauf stdin suchen, wenn es keine txtDatei 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 failglobOption für die (interessant für diese Diskussion, da im Gegensatz zu ashAT & T kshoder zsh, bashnicht 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, fishoder bash -O failglobin 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 zshmit , setopt cshnullglobobwohl ein vernünftiger Weg , es zu tun in zshsein würde wie ein Klacks zu verwenden:
ls -- *.(txt|html)
In zshund ksh93kö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 txtDatei gäbe, anstatt den Befehl mit einem Fehler fehlzuschlagen (oder es zu einem Array mit einem *.txtLiteralargument mit anderen Shells zu machen).
Versionen fishvor 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 zshAusnahme von Klümpchen verwendet in for, setoder 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/globHelper ausgeführt, und dieser Helper verhielt sich wie cshfolgt: 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 $1der /etc/globbei Verwendung von $1Platzhaltern 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.whateverbdas 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).