Lösung 1:
echo "$(uniq .bash_history)" > .bash_history
sollte das gewünschte Ergebnis haben. Die Subshell wird vor .bash_history
ausgeführt ist zum Schreiben geöffnet. Wie in Phil Ps Antwort erklärt, bis zum Zeitpunkt .bash_history
im ursprünglichen Befehl gelesen wird, wurde er bereits um die >
abgeschnitten Betreiber.
Lösung 2:
Ich empfehle die Verwendung von sponge
von moreutils. Aus der Manpage:
DESCRIPTION
sponge reads standard input and writes it out to the specified file. Unlike
a shell redirect, sponge soaks up all its input before opening the output file.
This allows for constructing pipelines that read from and write to the same
file.
Um dies auf Ihr Problem anzuwenden, versuchen Sie:
uniq .bash_history | sponge .bash_history
Lösung 3:
Das Problem besteht darin, dass Ihre Shell die Befehlspipeline einrichtet, bevor die Befehle ausgeführt werden. Es geht nicht um "Eingabe und Ausgabe", sondern darum, dass der Inhalt der Datei schon weg ist, bevor uniq überhaupt läuft. Es geht ungefähr so:
- Die Shell öffnet den
>
Ausgabedatei zum Schreiben, Abschneiden - Die Shell richtet sich so ein, dass der Dateideskriptor 1 (für stdout) für diese Ausgabe verwendet wird
- Die Shell führt uniq aus, vielleicht so etwas wie execlp("uniq", "uniq", ".bash_history", NULL)
- uniq läuft, öffnet .bash_history und findet dort nichts
Es gibt verschiedene Lösungen, einschließlich der Bearbeitung vor Ort und der Verwendung temporärer Dateien, die andere erwähnen, aber der Schlüssel liegt darin, das Problem zu verstehen, was tatsächlich schief läuft und warum.
Lösung 4:
Ein weiterer Trick, um dies zu tun, ohne sponge
zu verwenden , ist der folgende Befehl:
{ rm .bash_history && uniq > .bash_history; } < .bash_history
Dies ist einer der Cheats, die in dem hervorragenden Artikel „In-Place“-Bearbeitung von Dateien auf backreference.org beschrieben werden.
Es öffnet im Grunde die Datei zum Lesen und "entfernt" sie dann. Es wird jedoch nicht wirklich entfernt:Es gibt einen offenen Dateideskriptor, der darauf zeigt, und solange dieser geöffnet bleibt, ist die Datei immer noch vorhanden. Dann erstellt es eine neue Datei mit demselben Namen und schreibt die eindeutigen Zeilen hinein.
Nachteil dieser Lösung:Wenn uniq
aus irgendeinem Grund fehlschlägt, wird Ihr Verlauf gelöscht.
Lösung 5:
Schwamm von moreutils verwenden
uniq .bash_history | sponge .bash_history