GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Warum ist Nullglob kein Standard?

In den meisten Shells nullglob ist nicht die Vorgabe. Das bedeutet zum Beispiel, wenn Sie diesen Befehl ausführen

ls *

in einem leeren Verzeichnis wird * erweitert glob zu einem wörtlichen * , statt zu einer leeren Liste von Argumenten. Es gibt Möglichkeiten, dieses Verhalten zu ändern, sodass * in einem leeren Verzeichnis wird eine leere Liste von Argumenten zurückgeben, was intuitiver erscheint.

Gibt es also einen Grund, warum nullglob ist standardmäßig deaktiviert? Wenn ja, was ist das?

Akzeptierte Antwort:

Der nullglob Option (was übrigens ein zsh ist Erfindung, erst Jahre später zu bash hinzugefügt (2.0 )) 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 ausführen ohne Argument, das als ls -- . behandelt wird (Listen Sie das aktuelle Verzeichnis auf), wenn keine Dateien übereinstimmen, was wahrscheinlich schlimmer ist, als ls aufzurufen mit einem wörtlichen *.txt als Argument.

Sie haben ähnliche Probleme mit den meisten Textdienstprogrammen:

grep foo *.txt

Würde nach foo suchen auf stdin, wenn es kein txt gibt Datei.

Eine vernünftigere Standardeinstellung, und zwar die von csh, tcsh, zsh oder fish 2.3+ (und von frühen Unix-Shells), besteht darin, den Befehl vollständig abzubrechen, wenn der Glob nicht übereinstimmt.

bash (seit Version 3) hat einen failglob Option dafür (interessant für diese Diskussion, da im Gegensatz zu ash , AT&T ksh oder zsh , bash unterstützt keine lokalen Gültigkeitsbereiche für Optionen (obwohl sich das in 4.4 ändern wird), diese Option macht, wenn sie global aktiviert ist, ein paar Dinge kaputt, wie die Bash-Vervollständigungsfunktionen).

Beachten Sie, dass sich csh und tcsh leicht von zsh unterscheiden , fish oder bash -O failglob in Fällen wie:

ls -- *.txt *.html

Wo alle Globs nicht übereinstimmen müssen, damit der Befehl abgebrochen wird. Wenn es beispielsweise eine txt-Datei und keine html-Datei gibt, wird das zu:

ls -- file.txt

Sie können dieses Verhalten mit zsh erreichen mit setopt cshnullglob obwohl ein vernünftigerer Weg, es in zsh zu tun wäre ein Glob wie:

ls -- *.(txt|html)

In zsh und ksh93 , können Sie auch nullglob anwenden auf einer Pro-Glob-Basis, was ein viel vernünftigerer Ansatz ist, als eine globale Einstellung zu ändern:

files=(*.txt(N))  # zsh
files=(~(N)*.txt) # ksh93

würde ein leeres Array erstellen, wenn es kein txt gibt Datei, anstatt den Befehl mit einem Fehler abzubrechen (oder es zu einem Array mit einer *.txt wörtliches Argument mit anderen Shells).

Versionen von fish vor 2.3 würde wie bash -O nullglob funktionieren aber bei Interaktivität eine Warnung ausgeben, wenn ein Glob keine Übereinstimmung hat. Seit 2.3 funktioniert es wie zsh außer Globs, die in for verwendet werden , set oder count .

Nun, zur Historie, das Verhalten war tatsächlich kaputt durch die Bourne-Shell. In früheren Unix-Versionen erfolgte das Globbing über /etc/glob Helfer und dieser Helfer verhielt sich wie csh :Der Befehl würde fehlschlagen, wenn keiner der Globs mit einer Datei übereinstimmt, und andernfalls würden die Globs ohne Übereinstimmung entfernt.

Verwandte:Bash + wie kann man das sekundäre Skript und das Hauptskript gleichzeitig verlassen?

Die Situation, in der wir uns heute befinden, ist also auf eine schlechte Entscheidung zurückzuführen, die in der Bourne-Shell getroffen wurde.

Beachten Sie, dass die Bourne-Shell (und die C-Shell) mit einem weiteren neuen Unix-Feature ausgestattet waren:der Umgebung. Das bedeutete Variablenerweiterung (der Vorgänger hatte nur den $1 , $2 … Positionsparameter). Die Bourne-Shell hat auch die Befehlssubstitution eingeführt.

Eine weitere schlechte Entwurfsentscheidung der Bourne-Shell bestand darin, bei der Erweiterung von Variablen und der Befehlsersetzung Globbing (und Splitting) durchzuführen (möglicherweise aus Gründen der Abwärtskompatibilität mit der Thompson-Shell, in der echo $1 würde immer noch /etc/glob aufrufen wenn $1 enthaltene Platzhalter (es war dort eher eine Präprozessor-Makroerweiterung, da der erweiterte Wert erneut als Shell-Code geparst wurde)).

Fehlerhafte Globs, die nicht übereinstimmen, würden beispielsweise Folgendes bedeuten:

pattern='a.*b'
grep $pattern file

würde der Befehl fehlschlagen (es sei denn, es gibt einige a.whateverb Dateien im aktuellen Verzeichnis). csh (der auch Globbing bei der Variablenerweiterung durchführt) schlägt in diesem Fall fehl (und ich würde argumentieren, dass es besser ist, als einen schlafenden Fehler dort zu belassen, selbst wenn es nicht so gut ist, überhaupt kein Globbing zu machen, wie in zsh ).


Linux
  1. Warum eine lange Verzögerung, nachdem der Befehl nicht gefunden wurde?

  2. Linux – Warum funktioniert Setuid nicht?

  3. Warum funktioniert `exit &` nicht?

  4. Warum ist Lpd bei der Übertragung nicht standardmäßig aktiviert?

  5. file_put_contents erstellt keine txt-Datei

Warum „löschen“ den ganzen Bildschirm nicht löschen?

warum funktioniert sftp rmdir nicht?

Warum verwenden wir su - und nicht nur su?

Fedora 25 verwendet standardmäßig NICHT Wayland!

Warum reicht das Löschen des Bash-Verlaufs nicht aus?

Warum nicht ICMP blockieren?