In den meisten Shells nullglob
ist dies nicht der Standard. Das heißt zum Beispiel, wenn Sie diesen Befehl ausführen
ls *
In einem leeren Verzeichnis wird der *
Glob zu einem Literal *
und nicht zu einer leeren Liste von Argumenten erweitert. Es gibt Möglichkeiten, dieses Verhalten zu ändern, sodass *
in einem leeren Verzeichnis eine leere Liste von Argumenten zurückgegeben wird, die intuitiver zu sein scheinen.
Gibt es einen Grund, warum nullglob
standardmäßig deaktiviert ist? Wenn ja, aus welchem Grund?
*
es sich um ein Glob handelt, und es wird auf alle vorhandenen Dateien ausgeweitet . Wie ist es "intuitiv", wenn in einem speziellen Fall leere Verzeichnis-Globs zu einem Literal "erweitert" werden*
?Antworten:
Die
nullglob
Option (bei der es sich übrigens um einezsh
Erfindung handelt, die erst Jahre später zubash
(2.0
) hinzugefügt wurde ) wäre in einigen Fällen nicht ideal. Undls
ist ein gutes Beispiel:Oder sein korrekteres Äquivalent:
Mit
nullglob
on würdels
ohne Argument ausgeführt, das wie folgt behandelt wirdls -- .
(das aktuelle Verzeichnis auflisten), wenn keine Dateien übereinstimmen. Dies ist wahrscheinlich schlimmer als der Aufrufls
mit einem Literal*.txt
als Argument.Bei den meisten Textdienstprogrammen treten ähnliche Probleme auf:
Würde
foo
auf stdin suchen, wenn es keinetxt
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) einefailglob
Option für die (interessant für diese Diskussion, da im Gegensatz zuash
AT & Tksh
oderzsh
,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
oderbash -O failglob
in Fällen wie: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:
Sie können dieses Verhalten bekommen
zsh
mit ,setopt cshnullglob
obwohl ein vernünftiger Weg , es zu tun inzsh
sein würde wie ein Klacks zu verwenden:In
zsh
undksh93
können Sie nullglob auch global anwenden. Dies ist weitaus vernünftiger als das Ändern einer globalen Einstellung: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 funktionierenbash -O nullglob
, geben aber eine Warnung aus, wenn sie interaktiv sind, wenn ein Glob keine Übereinstimmung hat. Seit 2.3, funktioniert es wie mitzsh
Ausnahme von Klümpchen verwendet infor
,set
odercount
.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 wiecsh
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:
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ührenzsh
).quelle
nullglob
Scheint, die Tab-Vervollständigung zu unterbrechen (das Drücken der Tab-Taste führt zu nichts, wenn sie aktiviert ist).files=$(shopt -s nullglob;echo *.txt)
xpg_echo
) in skalare Variablen speichert . Man braucht so etwas wiereadarray -td '' files < <(shopt -s nullglob; printf '%s\0' *.txt)
mitbash
4.4 oder höher oder(shopt -s nullglob; printf '%s\0' *.txt) | xargs -r0 cmd
mit GNUxargs
, um überhaupt mit beliebigen Dateinamen arbeiten zu können. Oder verwenden Sie noch mit bash4.4 eine Hilfsfunktion, dielocal -
(25 Jahre später von ash kopiert) einen lokalen Bereich für Optionen verwendet.