Ich habe eine Datei temp.txt, die ich mit dem sort
Befehl in bash sortieren möchte .
Ich möchte, dass die sortierten Ergebnisse die Originaldatei ersetzen.
Dies funktioniert zum Beispiel nicht (ich bekomme eine leere Datei):
sortx temp.txt > temp.txt
Kann dies in einer Zeile erfolgen, ohne auf temporäre Dateien kopieren zu müssen?
EDIT: Die -o
Option ist sehr cool für sort
. Ich habe sort
in meiner Frage als Beispiel verwendet. Ich habe das gleiche Problem mit anderen Befehlen:
uniq temp.txt > temp.txt.
Gibt es eine bessere allgemeine Lösung?
Antworten:
quelle
sort --inplace *.txt
? Das wäre verrückt coolfind . -name \*.txt -exec sort {} -o {} \;
A
sort
muss alle Eingaben sehen, bevor die Ausgabe beginnen kann. Aus diesem Grund kann dassort
Programm problemlos eine Option zum Ändern einer vorhandenen Datei anbieten:Im Einzelnen heißt es in der Dokumentation von GNU
sort
:Während die Dokumentation von BSD
sort
sagt:Befehle wie
uniq
können mit dem Schreiben der Ausgabe beginnen, bevor sie das Lesen der Eingabe beendet haben. Diese Befehle unterstützen normalerweise keine direkte Bearbeitung (und es wäre schwieriger für sie, diese Funktion zu unterstützen).Normalerweise umgehen Sie dies mit einer temporären Datei. Wenn Sie unbedingt eine Zwischendatei vermeiden möchten, können Sie das gesamte Ergebnis in einem Puffer speichern, bevor Sie es ausschreiben. Zum Beispiel mit
perl
:Hier liest der Perl-Teil die gesamte Ausgabe von
uniq
in Variable$_
und überschreibt dann die Originaldatei mit diesen Daten. Sie können dasselbe in der Skriptsprache Ihrer Wahl tun, vielleicht sogar in Bash. Beachten Sie jedoch, dass genügend Speicher zum Speichern der gesamten Datei erforderlich ist. Dies ist bei der Arbeit mit großen Dateien nicht ratsam.quelle
Hier ist ein allgemeinerer Ansatz, arbeitet mit Uniq, Sort und so weiter.
quelle
sponge
den moreutils :cat file |frobnicate |sponge file
.Tobus Kommentar zu Schwamm rechtfertigt eine eigenständige Antwort.
Um von der moreutils- Homepage zu zitieren :
Leidet jedoch
sponge
unter dem gleichen Problem, das Steve Jessop hier kommentiert. Wenn einer der Befehle in der Pipeline zuvorsponge
fehlschlägt, wird die Originaldatei überschrieben.Oh,
my-important-file
ist weg.quelle
set -o pipefail
am Anfang Ihres Skripts hinzufügen , würde der Fehler ammistyped_command my-important-file
dazu führen, dass das Skript sofort vor der Ausführung beendet wirdsponge
, wodurch die wichtige Datei erhalten bleibt.Los geht's, eine Zeile:
Technisch gesehen gibt es kein Kopieren in eine temporäre Datei, und der Befehl 'mv' sollte sofort ausgeführt werden.
quelle
Ich mag die
sort file -o file
Antwort, möchte aber nicht zweimal denselben Dateinamen eingeben.Verwenden der BASH- Verlaufserweiterung :
Nimmt das erste Argument der aktuellen Zeile, wenn Sie drücken enter.
Eine einzigartige Sorte vor Ort:
greift nach dem letzten Argument in der aktuellen Zeile.
quelle
Viele haben die Option -o erwähnt . Hier ist der Manpage-Teil.
Von der Manpage:
quelle
Dies wäre stark speicherbeschränkt, aber Sie könnten awk verwenden, um die Zwischendaten im Speicher zu speichern und sie dann wieder auszuschreiben.
quelle
>
Datei abgeschnitten wird, bevor der Befehl (uniq
in diesem Fall) sie liest.Eine Alternative zu
sponge
den häufigerensed
:Es funktioniert für jeden Befehl (
sort
,uniq
,tac
, ...) und verwendet die sehr gut bekanntsed
ist-i
Option (Bearbeiten von Dateien in-place).Warnung: Versuchen Sie es
command file
zuerst, da das Bearbeiten von Dateien von Natur aus nicht sicher ist.Erläuterung
Erstens Sie sagen
sed
nicht die (original) Linien (drucken-n
Option ), und mit Hilfe dessed
‚sr
Kommandos undbash
‘ s - Prozess Substitution , der erzeugte Inhalt durch<(command file)
wird die Ausgabe gespeichert werden anstelle .Die Dinge noch einfacher machen
Sie können diese Lösung in eine Funktion einbinden:
Beispiel
quelle
Verwenden Sie das Argument
--output=
oder-o
Gerade auf FreeBSD ausprobiert:
quelle
uniq
Was sind die Nachteile, um die Funktion hinzuzufügen :quelle
Informieren Sie sich über den nicht interaktiven Editor
ex
.quelle
Wenn Sie darauf bestehen, das
sort
Programm zu verwenden, müssen Sie eine Zwischendatei verwenden - ich glaube, essort
gibt keine Option zum Sortieren im Speicher. Jeder andere Trick mit stdin / stdout schlägt fehl, es sei denn, Sie können garantieren, dass die Puffergröße für stdin von sort groß genug ist, um in die gesamte Datei zu passen.Edit: Schande über mich.
sort temp.txt -o temp.txt
funktioniert hervorragend.quelle
Eine andere Lösung:
quelle
<>
Trick nur in diesem Fall funktioniert, dauniq
er nur Eingabezeilen in Ausgabezeilen kopiert und einige auf dem Weg fallen lässt. Wenn anderer Befehl (zBsed
) verwendet , die die Eingabe ändern würde (zB würde jede Änderunga
inaa
), dann kann es außer Kraft setztfile
auf eine Weise , die keinen Sinn und sogar Schleife unendlich machen, vorausgesetzt , dass der Eingang ausreichend groß ist (mehr als ein einzelner Lesepuffer).