Wie funktionieren `>` und `>>`?

9

Ich habe versucht, reveine Datei zu erstellen und sie dann weiterzuleiten, cat > same_fileaber sie wurde zu einer leeren Datei.

Während ich es versuchte rev file.txt | cat > file2.txt && mv file.txt file2.txt;, funktionierte es.

Hat sogar rev file.txt | cat >> file.txt;funktioniert.

Aber als ich es versuchte rev file.txt | cat > file.txt, schlug es fehl.

Vintux
quelle
Sie können auch so auslassen cat: rev file.txt > file2.txt && mv file2.txt file.txt. Dies ist eine überflüssige Verwendung voncat . Wenn Sie es weglassen, sparen Sie sich das Laichen eines zusätzlichen Prozesses.
Strategie

Antworten:

19

Das Grundlegende, was Sie in diesem Fall zwischen beiden Umleitungsarten (> und >>) verstehen müssen, ist:

>

Leitet die Informationen um und überschreibt sie, auf die sie verwiesen wurden. Dies geschieht beim Empfang von Informationen über die Pipe "|"

>>

Leitet die Informationen, auf die verwiesen wurde, um und verkettet sie. Dies geschieht beim Empfang von Informationen über die Pipe "|"

In beiden Fällen wird die Datei stattdessen erstellt, wenn sie nicht vorhanden ist. Nur bei ">>" werden die Informationen verkettet, wenn Sie sie erneut in derselben Datei ausführen. Mit ">" würden Sie einfach alles überschreiben, was Sie beim ersten Durchlauf getan haben.

Aber hier ist der Deal, wenn Sie dieselbe Eingabedatei wie die Ausgabedatei verwenden. In diesem speziellen Fall würden Sie, wenn Sie ">" verwenden, die Informationen entfernen, die der "Eingabe" -Teil analysieren muss, da die Ausgabedatei sie "überschreiben" würde. Also in:

rev file.txt | cat > file.txt

Was in der "Zeitlupenerklärung" tatsächlich passiert, ist:

  1. revbereitet sich darauf vor, den Inhalt von umzukehren file.txtund an Pipe zu senden
  2. Während revdie Informationen an Pipe gesendet werden, werden sie von Pipe direkt an Pipe übertragen cat.
  3. Während der catEmpfang der Informationen werden diese automatisch auf die Informationen angewendet, mit denen file.txtsie festgelegt wurden.
  4. Das Schlüsselwort hier ist "während", weil alles zur gleichen Zeit geschieht. Bitte beachten Sie die hervorragenden Kommentare von Emil, um ein tieferes Verständnis für diesen Teil zu erhalten.
  5. catIch werde nicht darauf warten rev, die gesamte Datei weiterzuleiten. Es beginnt einfach in der Minute, in der der erste Teil der Informationen eingeht. Je nachdem, welches Symbol Sie verwendet haben, wird eine Verbindung zu hergestellt file.txt.
  6. In diesem Fall schneidet die Shell die Ausgabedatei ab, da Sie > anstelle von >> verwendet haben. Dies bedeutet , dass die Informationen geöffnet und gelöscht werden,file.txt während auf die neuen Informationen gewartet wird. Mit >> würde eine Verbindung mit geöffnet file.txtund auf neue Informationen in der zuletzt erkannten Zeile gewartet.
  7. Da die Informationen bereits file.txtmit > gelöscht wurden , revwürde ich versuchen, ihre Arbeit zu erledigen und nichts zu bekommen, da catalles gelöscht wurde, um die neuen Informationen vorzubereiten.

Warum arbeiten die anderen nach dem Lesen der obigen Informationen? Deswegen:

rev file.txt | cat > file2.txt && mv file.txt file2.txt

Hier leiten Sie an cat weiter, die die Informationen an eine andere Datei sendet . In diesem Fall ist die verarbeitete Eingabedatei file.txtnicht mit der Ausgabedatei identisch file2.txt. Danach überschreiben Sie buchstäblich das Ganze file2.txtmit file.txt, sodass der gesamte Prozess von catgelöscht wurde. Grundsätzlich könnte die ganze Zeile vereinfacht werden, cp file.txt file2.txtweil sie das Gleiche tut, da sie file2.txtam Ende das verliert revund mit dem mvBefehl überschrieben wird .

rev file.txt | cat >> file.txt

In diesem Fall verketten Sie die Informationen mit derselben Datei. Es wird also nur eine Verbindung zu dieser Datei hergestellt, aber nicht die Informationen gelöscht, wie sie mit einem einzigen > angezeigt werden . Das Endergebnis sollte die ursprüngliche Information plus die umgekehrte Information sein.

Luis Alvarado
quelle
5
Die Datei wird von cat nicht abgeschnitten. Es wird von der Shell abgeschnitten, bevor überhaupt einer der Befehle in der Pipeline gestartet wird.
Emil Jeřábek
Richtig, suchte nach einfacheren Worten zu erklären. Da ist es ein bisschen schwer zu erklären, ob das OP nicht weiß, was für eine Shell es ist und so. Ich versuche es so "freundlich" wie möglich zu machen.
Luis Alvarado
1
Nun, es ist nicht wirklich wichtig, dass es von der Shell gemacht wird, aber dass das Timing, das Sie präsentieren, falsch ist. Das Abschneiden erfolgt nicht in Schritt 6, sondern in Schritt 0. rev file.txt | cat --bogus-option > file.txtAußerdem wird die Datei abgeschnitten, obwohl cat nicht versucht, sie zu öffnen.
Emil Jeřábek
@ EmilJeřábek du bist richtig. Benutzer, die nicht wissen, wie es sich verhält, werden es einfacher haben, wenn wir Schritt für Schritt nur mit den Befehlen fortfahren. Außerdem sendet Ihr Beispiel die Informationen immer noch an dieselbe Datei, sodass bash die gesamte Zeile liest, die Ausgabe sieht und sie weiterhin öffnet UND abschneidet. Der Fehler ist einfach die Ausgabe von stderr an stdout.
Luis Alvarado
4
Siehe auch moreutils , eine fantastische Sammlung von Tools (verfügbar im Paket-Repository als moreutils), einschließlich spongeeines Tools, das speziell für den Fall des Überschreibens einer Eingabedatei entwickelt wurde. Zum Beispiel rev file.txt >file2.txt && mv file2.txt file.txtwürde die Problemumgehung werden rev file.txt | sponge file.txt, was auch dann korrekt funktioniert, wenn bereits etwas benannt ist file2.txt.
Daniel Wagner
9

Wenn die Shell eine Umleitung sieht, öffnet sie zuerst die relevanten Dateien, bevor sie einen der beteiligten Befehle ausführt. Wenn Sie also Folgendes tun:

foo file.txt | bar > file.txt

Die Umleitung zu file.txtbewirkt , dass es vor dem foo Ausführen abgeschnitten wird und gelesen werden kann file.txt. Nebenbei bemerkt, dies ist der Grund, warum Sie nicht tun können:

sed 'blah' file.txt > file.txt

Und warum sedhat eine direkte Bearbeitungsoption.

Zuletzt tun:

.. | cat > file.txt

ist eine nutzlose Verwendung von Katze , insbesondere wenn Sie versuchen, von file.txtfrüher zu lesen .

Wenn Sie eine Datei direkt umkehren möchten, gibt es keine Verknüpfungen . Möglicherweise können Sie die sedoder awkTricks bei der direkten Bearbeitung verwenden.

muru
quelle
3

>ist ein Redirector (Operator), der die Ausgabe an etwas anderes sendet
(Eingabe des nächsten Befehls, Drucker ..)

In Ihrem Fall wird die Ausgabe in eine Datei verschoben file.txt. Wenn diese Datei bereits vorhanden ist, wird sie überschrieben, wenn sie nicht erstellt wird.

>>ist ein Append-Operator. Wenn file.txtbereits vorhanden, wird die Ausgabe an das Ende der Datei angehängt. Wenn die Datei nicht vorhanden ist, wird sie erstellt und die Ausgabe in die neue Datei geschrieben, genau wie >(Redirector).

Ken Mollerup
quelle
Das OP scheint dies verstanden zu haben. Die Verwirrung scheint nur darauf zurückzuführen zu sein, dass sich dieselbe Datei auf beiden Seiten des Operators >und des >>Operators befindet.
bzlm
0

Sie können Vim im Ex-Modus verwenden:

ex -sc '%!rev' -cx file.txt
  1. % Wählen Sie alle Zeilen aus

  2. ! Führen Sie den Befehl aus

  3. x speichern und schließen

Steven Penny
quelle