tl; dr
Nein >>
ist im Wesentlichen "immer nach dem Ende der Datei suchen", während >
ein Zeiger auf die zuletzt geschriebene Stelle beibehalten wird.
Volle Antwort
(Hinweis: Alle meine Tests wurden unter Debian GNU / Linux 9 durchgeführt.)
Noch ein Unterschied
Nein, sie sind nicht gleichwertig. Es gibt noch einen anderen Unterschied. Es kann sich unabhängig davon manifestieren, ob die Zieldatei zuvor vorhanden war oder nicht.
Führen Sie dazu einen Prozess aus, der Daten generiert und mit >
oder >>
(z pv -L 10k /dev/urandom > blob
. B. ) in eine Datei umleitet . Lass es laufen und ändere die Größe der Datei (zB mit truncate
). Sie werden sehen, dass >
das (wachsende) Offset erhalten >>
bleibt, während es immer an das Ende angehängt wird.
- Wenn Sie die Datei auf eine kleinere Größe kürzen (die Größe kann Null sein)
>
ist egal, es wird am gewünschten Offset geschrieben, als ob nichts passiert wäre; unmittelbar nachdem das Abschneiden des Offsets über das Ende der Datei hinausgeht, wird die Datei ihre alte Größe wiedererlangen und weiter wachsen. Fehlende Daten werden mit Nullen gefüllt (möglichst sparsam).
>>
wird an das neue Ende angehängt, wächst die Datei von ihrer abgeschnittenen Größe.
- Wenn Sie die Datei vergrößern
>
ist egal, es wird am gewünschten Offset geschrieben, als ob nichts passiert wäre; Unmittelbar nach dem Ändern der Größe befindet sich der Versatz irgendwo in der Datei. Dies führt dazu, dass die Datei für eine Weile nicht mehr wächst, bis der Versatz das neue Ende erreicht. Dann wächst die Datei normal.
>>
wird an das neue Ende angehängt, wird die Datei von ihrer vergrößerten Größe vergrößert.
Ein weiteres Beispiel ist das Anhängen (mit einem separaten >>
) einer zusätzlichen Angabe, wenn der Datenerzeugungsprozess ausgeführt wird und in die Datei geschrieben wird. Dies ähnelt dem Vergrößern der Datei.
- Der Erzeugungsprozess mit
>
schreibt an seinem gewünschten Versatz und überschreibt schließlich die zusätzlichen Daten.
- Der Erzeugungsprozess mit
>>
überspringt die neuen Daten und fügt sie an (möglicherweise tritt eine Race-Bedingung auf, die beiden Streams verschachteln sich möglicherweise, es sollten jedoch keine Daten überschrieben werden).
Beispiel
Ist es in der Praxis wichtig? Es gibt diese Frage :
Ich führe einen Prozess aus, der viel Ausgabe auf stdout produziert. Alles in eine Datei senden [...] Kann ich eine Art Protokollrotationsprogramm verwenden?
Diese Antwort besagt, dass die Lösung logrotate
mit der folgenden copytruncate
Option vorliegt:
Kürzen Sie die ursprüngliche Protokolldatei, nachdem Sie eine Kopie erstellt haben, anstatt die alte Protokolldatei zu verschieben und optional eine neue zu erstellen.
Nach dem, was ich oben geschrieben habe, >
wird das abgeschnittene Protokoll durch Umleiten mit in kürzester Zeit groß. Sparsamkeit spart den Tag, es sollte kein nennenswerter Speicherplatz verschwendet werden. Trotzdem enthält jedes aufeinanderfolgende Protokoll immer mehr führende Nullen, die völlig unnötig sind.
Wenn Sie jedoch logrotate
Kopien erstellen, ohne die Sparsamkeit zu wahren, benötigen diese führenden Nullen mit jeder Kopie mehr Speicherplatz. Ich habe das Verhalten des Tools noch nicht untersucht. Es ist möglicherweise intelligent genug, wenn die Komprimierung spontan oder spärlich erfolgt (sofern die Komprimierung aktiviert ist). Dennoch können die Nullen nur Ärger verursachen oder bestenfalls neutral sein; nichts Gutes in ihnen.
In diesem Fall ist using >>
statt >
deutlich besser, auch wenn die Zieldatei gerade erstellt wird.
Performance
Wie wir sehen können, verhalten sich die beiden Operatoren nicht nur zu Beginn, sondern auch später unterschiedlich. Dies kann zu (geringfügigen?) Leistungsunterschieden führen. Im Moment habe ich keine aussagekräftigen Testergebnisse, die dies bestätigen oder widerlegen könnten, aber ich denke, Sie sollten nicht automatisch davon ausgehen, dass ihre Leistung im Allgemeinen gleich ist.
>>
wird im Wesentlichen "immer nach dem Ende der Datei suchen", während>
ein Zeiger auf die zuletzt geschriebene Stelle beibehalten wird. Es sieht so aus, als>>
Verwendet auf der Ebene des Systemaufrufs dasO_APPEND
Flag toopen()
. Und tatsächlich>
verwendetO_TRUNC
, während>>
nicht. Die Kombination vonO_TRUNC | O_APPEND
wäre auch möglich, die Shell-Sprache bietet diese Funktion einfach nicht.O_APPEND
mit einemlseek()
vor jedem zu emulieren,write()
wäre jedoch unterschiedlich, da dies den zusätzlichen Systemaufruf-Overhead bedeuten würde. (Und natürlich würde es nicht funktionieren, da ein anderer Prozesswrite()
dazwischen liegen könnte.)