Ich spielte mit Expansion herum und bemerkte ein merkwürdiges Verhalten. Ich habe versucht:
echo ./*.txt
Und ich hatte keine TXT-Datei in meinem aktuellen Verzeichnis. Die Ausgabe, die ich bekam, war:
./*.txt
Ich bin nur neugierig: Warum habe ich das bekommen? Ich hatte erwartet, keine Ausgabe zu bekommen.
PS: Als ich eine .txt
Datei hatte, wurde die Erweiterung richtig interpretiert. Mit anderen Worten, sagen wir, ich hätte eine Datei smthn.txt
, das Echo hallte tatsächlich wider current_directory/smthn.txt
.
quelle
shopt -s nullglob
werden leere Zeichenfolgen für nicht übereinstimmende Muster undshopt -u nullglob
(Standardeinstellung) das Muster selbst ausgegeben.Wenn dies
nullglob
die Standardeinstellung wäre, würden sich viele Befehle ganz unerwartet verhalten, da es (möglicherweise leider) üblich ist, dass Befehle den Fall von Null- Dateinamen-Argumenten qualitativ anders behandeln als den Fall von einem oder mehreren Dateinamen-Argumenten.Angenommen, Sie haben aktiviert
nullglob
(shopt -s nullglob
) und befinden sich in einem Verzeichnis, in dem keine Dateien übereinstimmen*.txt
. Dann*.txt
wird sich in der Tat zu nichts ausdehnen - kein leeres Feld, aber überhaupt keine Felder - wie Sie es erwartet haben. Aber das hätte folgende Ergebnisse:ls *.txt
würde alle Dateien im aktuellen Verzeichnis auflisten (außer versteckte Dateien), da dies derls
Fall ist, wenn Sie keine Dateinamenargumente übergeben.cat *.txt
würde von der Standardeingabe lesen , denn wenncat
es keine Dateinamenargumente gibt, ist es, als ob Sie ausgeführt würdencat -
. Wenn es interaktiv ausgeführt wird, wartet es auf Eingaben. Viele Befehle verhalten sich so.cp *.txt dest/
würde mit dem Fehler scheiterncp: missing destination file operand after 'dest/'
. Dies ist keine Katastrophe, aber es ist verwirrend und ganz anders als der stille Erfolg, der wahrscheinlich erwünscht ist.file *.txt
und verschiedene andere Programme ohne spezielles Verhalten für den Fall von Argumenten mit dem Dateinamen Null würden immer noch mit einer Fehler- oder Verwendungsmeldung fehlschlagen, wenn keine übergeben werden.printf 'Got file: "%s"\n' *.txt
würdeGot file: ""
statt nichts drucken .*
,?
und[
die sind nicht beabsichtigt , von dem Shell öfter offensichtlich falschen Ergebnisse produzieren würde erweitert werden, aber in einer Weise, um herauszufinden , könnte schwierig sein. Wenn beispielsweise keine Dateinamen im aktuellen Verzeichnis mit beginnengedit
, wirdapt list gedit*
(woapt list 'gedit*'
beabsichtigt) gerechtapt list
und listet alle verfügbaren Pakete auf.Es ist also gut, dass Sie dieses Verhalten nicht erhalten, ohne es anzufordern. Die wahrscheinlich häufigste praktische Situation, die tatsächlich durch vereinfacht wird,
nullglob
istfor f in *.txt
. Siehe auch diese Frage (mit der Sergiy Kolodyazhnyys Antwort verknüpft ist).Die schwierigere Frage ist, warum -
failglob
wo es ein Erweiterungsfehler ist, einen Glob zu haben, der nicht mit Dateien übereinstimmt - nicht die Standardeinstellung in Bash ist. Ich glaube, Sergiy Kolodyazhnyys Antwort erfasst den Grund dafür, auch ohne ihn direkt anzusprechen. Nicht beibehaltene Globs beizubehalten, ohne einen Expansionsfehler zu erzeugen, ist (möglicherweise leider) das standardisierte Verhalten, und es ist auch traditionelles und daher erwartetes Verhalten. Obwohl bash nicht versucht, vollständig POSIX-kompatibel zu sein, es sei denn, es wird mit dem Namen aufgerufensh
oder die--posix
Option übergeben, folgen viele seiner Entwurfsoptionen, auch wenn es sich nicht im POSIX-Modus befindet, direkt POSIX. Sie mussten sich für ein Verhalten entscheiden, und es gibt Nachteile, die damit verbunden sind, den Erwartungen der Benutzer zu widersprechen.Ich denke, dies ist der am wenigsten historisch einflussreiche Aspekt der Angelegenheit, also habe ich ihn zum letzten Mal gespeichert ... aber es ist erwähnenswert, dass
nullglob
Verhalten konzeptionell etwas Seltsames ist .nullglob
erscheint auf den ersten Blick elegant, da syntaktisch der Fall von null übereinstimmenden Dateien nicht anders behandelt wird als der Fall von eins, zwei oder einer anderen Zahl. Die von uns ausgeführten Befehle, für die Globs zu Argumenten erweitert werden , behandeln sie normalerweise nicht gleich, wie oben beschrieben. Aber syntaktisch fühlt sich das zumindest richtig an, was meiner Meinung nach die Motivation für Ihre Frage ist.Und doch gibt es eine andere, subtilere Inkonsistenz,
nullglob
die nicht angesprochen wird - die sie tatsächlich verstärkt. Der Fall von Null-Globbing-Zeichen ("Platzhalter") wird grundlegend anders behandelt als der von einer, zwei oder einer anderen Zahl. Zum Beispiel mitshopt -s nullglob
, wennab?d?f
keine Dateien übereinstimmen, wird es entfernt; Wennab?d
keine Dateien übereinstimmen, werden sie entfernt. Wennab
jedoch keine Dateien übereinstimmen (dh wenn keine Datei vorhanden ist, deren Name genau lautetab
), wird sie immer noch nicht entfernt. Natürlich wäre es eine Katastrophe, wenn es entfernt würde, da es möglicherweise überhaupt nicht beabsichtigt ist, auf eine vorhandene Datei im aktuellen Verzeichnis zu verweisen. Es verweist möglicherweise nicht einmal auf eine Datei. Damit entfällt jedoch die Hoffnung auf völlige Beständigkeit.Die drei Verhaltensweisen, die Bash bietet - die Standardeinstellung, Globs, die nicht mit Dateien übereinstimmen, so zu behandeln, als wären sie keine Globs, und sie nicht zu erweitern, das Verhalten, das Sie von ihrer Behandlung erwartet haben (wenn Sie diese seltsame Wendung verzeihen) Dies bedeutet, dass alle Nullen der übereinstimmenden Dateien (
nullglob
) und das sichere Verhalten, sie als Fehler zu betrachten (failglob
), unterschiedliche Ansätze für die der Shell innewohnende Mehrdeutigkeit darstellen, die nicht wissen kann, ob ein bestimmtes Wort a sein soll Dateiname. Die Shell führt ihre Erweiterungen durch, ohne zu wissen, wie die von ihr aufgerufenen Befehle ihre Argumente behandeln.Dies ist einer von vielen Fällen der Trennung von Bedenken . In Systemen, deren Design der Unix-Philosophie folgt, soll jedes Teil eines tun und es gut machen . Die Shell verarbeitet Text in Befehle und Argumente und ruft die Befehle auf, von denen die meisten außerhalb der Shell selbst liegen. Dies ist in der Regel viel schöner und vielseitiger als Systeme, bei denen die externen Befehle selbst für die Durchführung dieser Transformationen verantwortlich sind (wie bei den herkömmlichen Befehlsprozessoren unter DOS und Windows). Aber es hat gelegentlich Nachteile.
quelle
failglob
. Es kann also nicht die Standardeinstellung sein, da es nicht immer unterstützt wurde.Der Hauptgrund ist , weil dies ist das Standardverhalten von bestimmtem POSIX - der Standard , die Abdeckungen Kommandosprache Shell und unter anderem Mustervergleich (Muscheln wie
bash
,dash
Shell - Ubuntu standardmäßig/bin/sh
, undksh
folgen Sie diesem Standard). Ab Abschnitt 2.13.3 Muster für die Dateinamenerweiterung :Dies hat natürlich einen Nebeneffekt - passenden Dateinamen, der buchstäblich sein kann
*.txt
. Dienullglob
Option inbash
undzsh
kann helfen: Wenn diese Option über aktiviert istshopt -s nullglob
(und standardmäßig nicht aktiviert ist, was für diese Frage gilt), wird globstar auf eine leere Zeichenfolge erweitert, wenn keine passenden Dateinamen gefunden werden.ksh93
hat einen eigenen fortschrittlichen Mustervergleichsmechanismus, der den gleichen Effekt erzielt~(N)*.txt
Siehe auch Warum ist nullglob nicht standardmäßig?
quelle