Warum wird "sort <" $ f1 "" gegenüber "sort -" $ f1 "" bevorzugt, und warum wird dies "sort" "gegenüber" $ f1 "" bevorzugt?

29

Von https://unix.stackexchange.com/a/458074/674

Denken Sie daran, -- wenn Sie willkürliche Argumente an Befehle übergeben (oder wenn möglich, Umleitungen verwenden). So sort -- "$f1"oder besser sort < "$f1"statt sort "$f1".

Warum wird die Verwendung --und Umleitung bevorzugt ?

Warum wird es sort < "$f1"vorgezogen sort -- "$f1"?

Warum wird es sort -- "$f1"vorgezogen sort "$f1"?

Vielen Dank.

Tim
quelle

Antworten:

56
sort "$f1"

Fehler für Werte $f1, die mit -oder hier beginnen, für sorteinige, die mit beginnen +(kann schwerwiegende Konsequenzen für eine beispielsweise aufgerufene Datei haben -o/etc/passwd).

sort -- "$f1"

(wobei -- das Ende der Optionen signalisiert wird) behebt die meisten dieser Probleme, schlägt jedoch für die aufgerufene Datei immer noch fehl -(was so sortinterpretiert wird, dass sie stattdessen die Standardeingabe enthält).

sort < "$f1"

Hat diese Probleme nicht.

Hier ist es die Shell, die die Datei öffnet. Dies bedeutet auch, dass, wenn die Datei nicht geöffnet werden kann, eine möglicherweise nützlichere Fehlermeldung angezeigt wird (z. B. geben die meisten Shells die Zeilennummer im Skript an) und die Fehlermeldung bei Verwendung konsistent ist Umleitungen, wo immer möglich, um Dateien zu öffnen.

Und in

sort < "$f1" > out

(im Gegensatz zu sort -- "$f1" > out), wenn "$f1"nicht geöffnet werden kann, outwird nicht erstellt / abgeschnitten und sortnicht einmal ausgeführt.

Um eine mögliche Verwirrung zu beseitigen (siehe nachfolgende Kommentare), wird der Befehl nicht daran gehindert, die Datei zu öffnen mmap()oder sich in der Datei zu befinden lseek()(dies sortgilt auch nicht), vorausgesetzt, die Datei selbst ist suchbar. Der einzige Unterschied besteht darin, dass die Datei von der Shell früher und im Dateideskriptor 0 geöffnet wird, während der Befehl später möglicherweise einen anderen Dateideskriptor verwendet. Der Befehl kann immer noch nach / mmap suchen, das fd 0, wie es gefällt. Das darf nicht verwechselt werden, wenn der Standard cat file | cmddieses Mal cmdeine Pfeife ist, die nicht gemappt / gesucht werden kann.

Stéphane Chazelas
quelle
4
Denken Sie daran, dass die Verwendung einer Umleitung sortdas sequentielle Lesen der Daten erzwingt und Sie mmapdie Datei nicht können. Auch sortwenn Sie möglicherweise nicht viele Probleme damit haben, sollten Sie die Leistung von less <fileund berücksichtigen less file. Im ersten Fall lessmuss der gesamte Inhalt der Datei im Speicher bleiben, im zweiten Fall dürfen nur die gewünschten Teile gelesen werden. Stellen Sie sich vor, das fileist eine 100-GB-Protokolldatei ...
Styroporfliege
7
@styrofoamfly: Es ist richtig, dass less <filealle Dateien im Speicher bleiben , aber es ist nicht gezwungen, dies ist ein Mangel von weniger. Nur cat file | lesswird dazu gezwungen. Check out less /dev/fd/0 <f, wodurch die Datei nicht im Speicher bleibt, obwohl sie auf stdin empfangen wird. Es ist ein weit verbreitetes Missverständnis, dass stdin unter Unix nicht zu finden ist. Es kann nämlich je nach Dateityp suchbar sein.
Pkt
@styrofoamfly Meinen Sie, dass read()Daten nacheinander aus einer Datei mmap()gelesen werden, während die gesamte Datei gleichzeitig in den Speicher eingelesen wird?
Tim
1
@JohnBollinger Nein. Das geht mindestens auf getopt von SysIII im Jahr 1980 zurück, bevor das GNU-Projekt gestartet wurde, und muss für die meisten Standarddienstprogramme, einschließlich sortPOSIX, unterstützt werden. Aber es ist wahr, dass es nicht immer unterstützt wird.
Stéphane Chazelas
2
Ich entschuldige mich, @ StéphaneChazelas, Sie haben Recht mit dem Ursprung der Konvention, und ich werde außerdem festlegen, dass die POSIX-Spezifikation für die getopt()C-Funktion diese Bedeutung des Arguments anerkennt --. Der wichtigste Punkt ist jedoch der, den Sie akzeptieren: Die Behandlung von Argumenten ist die Domäne einzelner Programme und wird nicht von allen --besonders behandelt .
John Bollinger
17

Das Problem sind Dateinamen, die mit einem Bindestrich beginnen. sort "$f1"funktioniert nicht, wenn der Wert von mit f1beginnt, -da der Befehl den Wert als Option interpretiert. Dies führt in der Regel zu einem Fehler, kann jedoch sogar zu einer Sicherheitslücke führen . Mit sort -- "$f1", die Doppelstrich Argument --mean „keine Optionen über diesen Punkt hinaus“ , so der Wert f1wird nicht als Option interpretiert werden. Es gibt jedoch noch einen Randfall: Wenn der Wert von f1ein Bindestrich ist und sonst nichts, dann ist es keine Option, sondern das Argument -, was „Standardeingabe“ bedeutet (weil das Argument eine Eingabedatei ist; für eine Ausgabedatei) es würde "Standardausgabe" bedeuten).

Durch die Verwendung der Umleitung werden alle diese Fallstricke vermieden.

Dies gilt nicht nur für die meisten Befehle sort.

Gilles 'SO - hör auf böse zu sein'
quelle
Wollen Sie damit sagen, dass sort < "$f1"dies funktionieren würde, wenn der Wert gleich wäre -? Es ist in keiner Schale, die ich ausprobiert habe.
Grawity
@grawity, vergleiche seq 10 > -; sort -mit seq 10 > -; sort < -.
Stéphane Chazelas