Warum wird beim Umleiten der Ausgabe einer Datei eine leere Datei erzeugt?

3683
seewalker

Warum wird beim Umleiten der Ausgabe einer Datei eine leere Datei erzeugt?

In Bash angegeben, warum

less foo.txt > foo.txt 

und

fold foo.txt > foo.txt 

Leer produzieren foo.txt? Da ein Anhang wie less eggs.py >> eggs.pyzwei Kopien des Textes erzeugt eggs.py, könnte man davon ausgehen, dass ein Überschreiben eine Kopie des Textes erzeugt.

Beachten Sie, ich sage nicht, dass dies ein Fehler ist, sondern eher ein Hinweis auf etwas tief in Unix.

17

2 Antworten auf die Frage

18
jlliagre

Bei Verwendung >wird die Datei im Abschneidemodus geöffnet, sodass der Inhalt entfernt wird, bevor der Befehl versucht, sie zu lesen.

Bei Verwendung >>wird die Datei im Anfügemodus geöffnet, so dass die vorhandenen Daten erhalten bleiben. Es ist jedoch immer noch ziemlich riskant, in diesem Fall dieselbe Datei als Eingabe und Ausgabe zu verwenden. Wenn die Datei groß genug ist, um nicht in die Größe des Lese-Eingabepuffers zu passen, wird sie möglicherweise unbegrenzt groß, bis das Dateisystem voll ist (oder Ihr Festplattenkontingent erreicht wird).

Wenn Sie eine Datei sowohl als Eingabe als auch als Ausgabe mit einem Befehl verwenden möchten, der keine Modifikation unterstützt, können Sie einige Problemumgehungen verwenden:

  • Verwenden Sie eine Zwischendatei und überschreiben Sie die Originaldatei, wenn Sie fertig sind und nur, wenn beim Ausführen des Dienstprogramms kein Fehler aufgetreten ist (dies ist der sicherste und gebräuchlichste Weg).

    fold foo.txt > fold.txt.$$ && mv fold.txt.$$ foo.txt 
  • Vermeiden Sie die Zwischendatei auf Kosten eines möglichen teilweisen oder vollständigen Datenverlusts, falls ein Fehler oder eine Unterbrechung auftritt. In diesem Beispiel werden die Inhalte von foo.txtals Eingabe an eine Subshell (innerhalb der Klammern) übergeben, bevor die Datei gelöscht wird. Der vorherige Inode bleibt am Leben, da die Subshell sie beim Lesen der Daten geöffnet hält. Die Datei, die vom inneren Dienstprogramm (hier fold) mit demselben Namen geschrieben wurde (foo.txt) weist auf einen anderen Inode hin, da der alte Verzeichniseintrag technisch so entfernt wurde, dass es zwei verschiedene "Dateien" mit demselben Namen während des Prozesses gibt. Wenn die Subshell beendet ist, wird der alte Inode freigegeben und seine Daten gehen verloren. Stellen Sie sicher, dass Sie genügend Speicherplatz haben, um die alte und die neue Datei gleichzeitig zu speichern, da sonst Daten verloren gehen.

    (rm foo.txt; fold > foo.txt) < foo.txt 
`sponge` from [moreutils](http://joeyh.name/code/moreutils/) can also help. `fold foo.txt | sponge foo.txt` – or `fold foo.txt | sponge !$` should also do. slhck vor 11 Jahren 3
@slhck Tatsächlich könnte Schwamm die Arbeit auch machen. Da dies jedoch weder von POSIX noch von Mainstream in Unix-ähnlichen Betriebssystemen festgelegt ist, ist es unwahrscheinlich, dass es vorhanden ist. jlliagre vor 11 Jahren 0
Es ist nicht so, dass es nicht * gemacht * werden kann;) slhck vor 11 Jahren 0
7
Ignacio Vazquez-Abrams

Die Datei wird von der Shell zum Schreiben geöffnet, bevor die Anwendung sie lesen kann. Wenn Sie die Datei zum Schreiben öffnen, wird sie abgeschnitten.