Warnung bezüglich '>'
Unix-Anfänger, die gerade etwas über die E / A-Umleitung gelernt haben ( <und >), probieren oft Dinge wie
befehl … eingabedatei > die_gleiche_datei
oder
befehle … < file > the_same_file
oder fast gleichwertig
cat Datei | befehl ...> die_gleiche_datei
( grep, sed, cut, sort, Und spellsind Beispiele für Befehle , die Menschen versucht sind , in Konstrukte wie diese zu verwenden.) Die Benutzer sind überrascht zu entdecken , dass diese Szenarien in der Datei führen immer leer.
Eine Nuance, die in der anderen Antwort nicht erwähnt zu sein scheint, lauert im ersten Satz des Redirection- Abschnitts von bash (1) :
Bevor ein Befehl ausgeführt wird, können seine Eingabe und Ausgabe unter
Verwendung einer speziellen Notation umgeleitet werden, die von der Shell interpretiert wird.
Die ersten fünf Wörter sollten fett, kursiv, unterstrichen, vergrößert, blinkend, rot gefärbt und mit einem
Symbol gekennzeichnet sein, um die Tatsache hervorzuheben, dass die Shell die angeforderten Umleitungen ausführt,
bevor der Befehl ausgeführt wird . Und erinnere dich auch
Die Umleitung der Ausgabe bewirkt, dass die Datei zum Schreiben geöffnet wird. Wenn die Datei nicht existiert, wird sie erstellt. Wenn es existiert, wird es auf die Größe Null gekürzt.
Also, in diesem Beispiel:
sort roster > roster
Die Shell öffnet die rosterDatei zum Schreiben und schneidet sie ab (dh, sie verwirft ihren gesamten Inhalt), bevor das sortProgramm ausgeführt wird. Natürlich kann nichts unternommen werden, um die Daten wiederherzustellen.
Man könnte das naiv erwarten
tr "[:upper:]" "[:lower:]" < poem > poem
könnte besser sein. Da die Shell Umleitungen von links nach rechts verarbeitet, wird sie poemzum Lesen geöffnet (für trdie Standardeingabe), bevor sie zum Schreiben geöffnet wird (für die Standardausgabe). Aber es hilft nicht. Obwohl diese Abfolge von Vorgängen zwei Dateizugriffsnummern ergibt, verweisen beide auf dieselbe Datei. Wenn die Shell die Datei zum Lesen öffnet, ist der Inhalt immer noch vorhanden, aber sie werden immer noch blockiert, bevor das Programm ausgeführt wird.
Also, was tun?
Die Lösungen umfassen:
Überprüfen Sie, ob das von Ihnen ausgeführte Programm über eine eigene interne Funktion verfügt, mit der Sie angeben können, wohin die Ausgabe gehen soll. Dies wird oft durch ein -o(oder --output=) Token angezeigt . Speziell,
sort roster -o roster
entspricht in etwa
sort roster > roster
Im ersten Fall sortöffnet das Programm die Ausgabedatei. Und es ist klug genug, die Ausgabedatei erst zu öffnen, nachdem sie alle Eingabedateien gelesen hat.
In ähnlicher Weise zumindest einige Versionen sedhaben eine -i(edit i n setzen) Option , die verwendet werden kann , die Ausgabe zurück an die Eingabedatei (wieder zu schreiben , nachdem alle Eingaben gelesen wurden). Editoren wie ed/ ex, emacs, picound vi/ vim
erlauben dem Benutzer eine Textdatei zu bearbeiten und die bearbeiteten Text in der Originaldatei speichern. Beachten Sie, dass ed(mindestens) nicht interaktiv verwendet werden kann.
vihat eine verwandte Funktion. Wenn Sie tippen , wird der Inhalt des Bearbeitungspuffers ausgegeben, die Ausgabe gelesen und in den Puffer eingefügt (wobei der ursprüngliche Inhalt ersetzt wird).:%!commandEntercommand
Einfach aber effektiv:
befehl … eingabedatei > temp_datei && mv temp_datei eingabedatei
Dies hat den Nachteil, dass input_fileein Link (wahrscheinlich) durch eine separate Datei ersetzt wird. Außerdem gehört die neue Datei Ihnen mit Standardschutz. Dies birgt insbesondere das Risiko, dass die Datei letztendlich weltweit lesbar ist, selbst wenn das Original dies input_filenicht wäre.
Variationen:
command … input_file > temp_file && cp temp_file input_file && rm temp_file
das wird immer noch (potenziell) die temp_fileWelt lesbar verlassen. Noch besser:
cp input_file temp_file && command … temp_file > input_file && rm temp_file
Dadurch bleiben der Link-Status, der Eigentümer und der Modus (Schutz) der Datei erhalten, was möglicherweise das Doppelte der E / A-Kosten zur Folge hat. (Möglicherweise müssen Sie eine Option wie -aoder -pon verwenden cp
, um die Attribute beizubehalten.)
command … input_file > temp_file &&
cp --attributes-only --preserve=all input_file temp_file &&
mv temp_file input_file
(Nur aus Gründen der Lesbarkeit in separate Zeilen unterteilt.) Dadurch wird der Modus der Datei (und, wenn Sie als Root angemeldet sind, als Eigentümer) beibehalten. separate Datei.
Dieser Blog
("In-Place" -Bearbeitung von Dateien) schlägt vor und erklärt
{rm eingabedatei && befehl ...> eingabedatei ; } < Eingabedatei
Dies setzt voraus, dass die commandStandardeingabe verarbeitet werden kann (aber fast alle Filter können). Der Blog selbst nennt dies einen riskanten Kludge und rät von seiner Verwendung ab. Dadurch wird auch eine neue, separate Datei erstellt (die mit nichts verknüpft ist), die Ihnen gehört und über Standardberechtigungen verfügt.
Das moreutils-Paket hat einen Befehl namens sponge:
befehl … eingabedatei | sponge the_same_file
Weitere Informationen finden Sie in dieser Antwort .
Folgendes hat mich völlig überrascht:
syntaxerror says :
[ Die meisten dieser Lösungen] werden auf einem schreibgeschützten Dateisystem versagen, wo „read-only“ bedeutet , dass Sie $HOME wird beschreibbar sein, sondern /tmpwerden nur gelesen werden (Standardeinstellung). Wenn Sie beispielsweise Ubuntu verwenden und die Wiederherstellungskonsole gestartet haben, ist dies normalerweise der Fall. Auch die hier-Dokument Betreiber <<<werden dort auch nicht funktionieren, da es erfordert /tmpwerden Lese- / Schreibzugriff ,
weil es eine temporäre Datei in auch dort schreiben.
(vgl. diese Frage enthält eine strace'd Ausgabe)
In diesem Fall kann Folgendes funktionieren:
Also, was war die Frage?
Dies war ein beliebtes Thema in U & L; es wird in den folgenden Fragen angesprochen:
… Und das zählt nicht Super User oder Ask Ubuntu. Ich habe viele Informationen aus den Antworten auf die obigen Fragen hier in diese Antwort aufgenommen, aber nicht alle. (Das heißt, für weitere Informationen lesen Sie die oben aufgeführten Fragen und deren Antworten.)
PS Ich habe keine Verbindung zu dem Blog, das ich oben zitiert habe.