Unterstützt sort das Sortieren einer Datei an Ort und Stelle, wie `sed - in-place`?

80

Bin ich blind oder gibt es keine Möglichkeit --in-placedafür sort?

Um die Ergebnisse in der Eingabedatei zu speichern, verwendet sed -i( --in-place).

Ausgabe von sortin die Eingabedatei umleiten

sort < f > f

führt dazu, dass es leer wird. Wenn es keine --in-placeOption gibt - gibt es vielleicht einen Trick, wie man das auf praktische Weise macht?

(Das einzige, was mir in den Sinn kommt:

sort < f > /tmp/f$$ ; cat /tmp/f$$ > f ; rm /tmp/f$$

Das Verschieben ist nicht die richtige Wahl, da die Dateiberechtigungen möglicherweise geändert werden. Deshalb überschreibe ich mit dem Inhalt der temporären Datei, die ich dann entferne.)

Grzegorz Wierzowiecki
quelle
Es gibt auch die insituMöglichkeit, beliebige Befehle direkt zu verwenden.
Sr_
@sr_, das ist ein interessanter Befehl, aber er funktioniert mit keinem Befehl, nur mit Befehlen, die nicht schneller schreiben als sie lesen (andernfalls wird die Eingabedatei gelöscht, bevor der Befehl sie liest). Es gibt keine Garantie, dass es funktioniert sort.
cjm 22.01.12
@cjm, ich bin wirklich nicht sicher, ist aber nicht das soll diesen Fall behandeln?
Sr_
@sr_, ich denke du hast recht. Ich habe die Beschreibung gelesen, anstatt auf die Quelle zu schauen. Obwohl für wirklich große Dateien möglicherweise nicht genügend Speicher für den Puffer und den Absturz vorhanden ist (es sieht nicht so aus, als würde nach einer NULL-Rückkehr von malloc gesucht).
cjm
@cjm: Oh ja, in der Tat.
Sr_

Antworten:

110

sorthat die -o, --outputOption, dass ein Dateiname als Argument verwendet wird. Wenn es mit der Eingabedatei identisch ist, wird das Ergebnis in eine temporäre Datei geschrieben und anschließend die ursprüngliche Eingabedatei überschrieben (genau das Gleiche wie bei der Eingabe sed -i).

Von GNU sortInfoseite:

`-o OUTPUT-FILE'
`--output=OUTPUT-FILE'
      Write output to OUTPUT-FILE instead of standard output.  Normally,
      `sort' reads all input before opening OUTPUT-FILE, so you can
      safely sort a file in place by using commands like `sort -o F F'
      and `cat F | sort -o F'.  However, `sort' with `--merge' (`-m')
      can open the output file before reading all input, so a command
      like `cat F | sort -m -o F - G' is not safe as `sort' might start
      writing `F' before `cat' is done reading it.

      On newer systems, `-o' cannot appear after an input file if
      `POSIXLY_CORRECT' is set, e.g., `sort F -o F'.  Portable scripts
      should specify `-o OUTPUT-FILE' before any input files.

und aus der Open Group Base-Spezifikation, Ausgabe 7 :

-o  output
    Specify the name of an output file to be used instead of the standard 
    output. This file can be the same as one of the input files.
Enzotib
quelle
Genau ! Es klappt ! Ich kann darin keine Ahnung finden man sort- ist es ein undokumentiertes Feature? Ist es Standard und tragbar?
Grzegorz Wierzowiecki
@GrzegorzWierzowiecki: siehe Update.
Enzotib
Gute Antwort :).
Grzegorz Wierzowiecki
1
Zusammenfassend: sort -o <filename> <filename>Sortiert eine Datei sicher an Ort und Stelle.
Phyatt
11

Sie können die spongeFunktion verwenden, die zuerst die Daten aufnimmt stdinund sie dann in eine Datei schreibt, wie zum Beispiel:

sort < f | sponge f

Der Nachteil spongeist, dass die Ausgabe temporär im Speicher abgelegt wird, was bei großen Dateien problematisch sein kann. Andernfalls müssen Sie es zuerst in eine Datei schreiben und dann die Originaldatei überschreiben.

Wie jedoch aus anderen Antworten hervorgeht, sind Vor-Ort-Änderungen im Allgemeinen keine gute Idee, da spongedie Maschine während eines Prozesses (zum Beispiel des einen) abstürzen kann und Sie dann sowohl die ursprüngliche als auch die neue Datei verlieren können. Sie sollten es zuerst in eine andere Datei schreiben und dann eine atomare mv(Verschiebungs-) Anweisung verwenden.

Willem Van Onsem
quelle
7

Es ist gefährlich, die Eingabedatei mit der Ausgabedatei zu überschreiben, da Sie beide verloren haben, wenn das Programm oder das System abstürzt, während die Datei geschrieben wird.

Einige Programme (meistens GNU-Versionen) haben eine In-Place-Option (z. B. -ifür Perl und GNU sed; -ofür GNU sort). Sie arbeiten, indem sie die Daten in eine temporäre Datei einfügen und an ihren Platz verschieben. Für Programme , die keine solche Option, haben Colin Watson - spongeDienstprogramm (im Joey Hess moreutils ) macht den Job sicher für jedes Programm (Beispiele: Kann ich cut? Eine Datei im Ort ändern ; Wie kann ich iconv die Eingabedatei mit dem konvertierten ersetzen machen Ausgabe? ).

Nur in den seltenen Fällen, in denen Sie die Originaldatei nicht mit denselben Berechtigungen neu erstellen können, empfehle ich, die Datei an Ort und Stelle zu überschreiben. In diesem Fall sollten Sie die ursprüngliche Eingabe lieber irgendwo speichern. Und dann können Sie einfach die Kopie der Eingabe verarbeiten und in die Originaldatei senden.

cp -p f ~/f.backup
sort <~/f.backup >|f
rm ~/f.backup # optional
Gilles
quelle
1
sort -oist nicht GNU-spezifisch und wurde speziell entwickelt, um die Datei an Ort und Stelle zu ändern. sortkann nicht mit dem Schreiben der Ausgabe beginnen, bevor die Eingaben nicht vollständig gelesen wurden (verwendet Speicher oder temporäre Dateien zum Speichern von Daten), daher sollte es ganz natürlich möglich sein, die Eingabe zu überschreiben.
Stéphane Chazelas
Tatsächlich ist es ein Fall, in dem GNU sortnicht POSIX ist, da sort -mo file1 file1 file2es nicht garantiert funktioniert, während herkömmliche sortAnwender wissen, wie man das umgeht (bereits in Unix V7 in den 70er Jahren).
Stéphane Chazelas
@JoelCross Odd, sort -ofunktioniert bei mir mit coreutils 8.25 und die Eigenschaft ist im Handbuch dokumentiert (wobei zu beachten ist, dass dies nur beim Sortieren und nicht beim Zusammenführen der Fall ist). Wenn Sie dies reproduzieren können, senden Sie einen Fehlerbericht (unter Angabe der genauen Befehlszeile, der genauen Eingabedatei (en), auf welchem ​​System Sie es ausführen und wie Sie die Binärdatei erhalten haben).
Gilles
4

Benutze -ooder probiere die vim-Methode:

$ ex -s +'%!sort' -cxa file.txt
Kenorb
quelle