Frage Wie füge ich am Anfang einer Datei in Bash Text hinzu?


Hi Ich möchte Text einer Datei voranstellen. Zum Beispiel möchte ich Aufgaben am Anfang einer todo.txt-Datei hinzufügen. Ich bin mir bewusst, dass echo 'task goes here' >> todo.txt aber das fügt die Zeile am Ende der Datei hinzu (nicht was ich will).


228
2018-02-17 03:21


Ursprung


Wenn es keine effiziente Möglichkeit gibt, das für große Dateien zu tun: unix.stackexchange.com/questions/87772/... - Ciro Santilli 新疆改造中心 六四事件 法轮功
Sehen Sie sich diese Methode an superuser.com/a/1352628/11116 - Evan Carroll


Antworten:


echo 'task goes here' | cat - todo.txt > temp && mv temp todo.txt

oder

sed -i '1s/^/task goes here\n/' todo.txt

oder

sed -i '1itask goes here' todo.txt

304
2018-02-17 03:34



der erste funktioniert super! Würde es Ihnen etwas ausmachen, die Logik zu erklären? Ich bin nicht besonders sicher, wie man die Syntax interpretiert. - user479534
@ user8347: Rohr (|) die Nachricht (echo '...') zu cat was benutzt - (Standardeingabe) als erste Datei und todo.txt als der zweite. cat conCATniert mehrere Dateien. Sende die Ausgabe (>) zu einer Datei namens temp. Wenn es keine Fehler gibt (&&) von cat dann umbenennen (mv) das temp Datei zurück in die ursprüngliche Datei (todo.txt). - Dennis Williamson
Ich kannte diese mögliche Syntax in seds letztem Beispiel nicht. Kann mir jemand sagen, wie diese Syntax heißt, damit ich mehr darüber suchen kann? - Kira
@Kira: Die 1 bedeutet, den nächsten Befehl nur in Zeile eins der Datei und der i Befehl ist einfügen. Suchen Sie in der Manpage unter dem Abschnitt "Addresses" und im Abschnitt "Zero or one address commands". - Dennis Williamson
@Terrance: Wenn dein sed Der Befehl sieht ungefähr so ​​aus (Einfügen einer führenden Registerkarte): '1i\tSome Text', müssen Sie möglicherweise den umgekehrten Schrägstrich verdoppeln. Ansonsten, dein Dialekt von sed kann nicht erkennen \t als Registerkarte. - Dennis Williamson


Eine einfachere Option ist meiner Meinung nach:

echo -e "task goes here\n$(cat todo.txt)" > todo.txt

Dies funktioniert, weil der Befehl innerhalb von $(...) wird vorher ausgeführt todo.txt wird mit überschrieben > todo.txt

Während die anderen Antworten gut funktionieren, finde ich das viel leichter zu merken, weil ich jeden Tag Echo und Katze benutze.

BEARBEITEN: Diese Lösung ist eine sehr schlechte Idee, wenn Backslashes auftreten todo.txt, weil dank der -e Flag echo wird sie interpretieren. Eine andere, viel einfachere Möglichkeit, Zeilenumbrüche in die Vorsatzzeichenfolge einzufügen, ist ...

echo "task goes here
$(cat todo.txt)" > todo.txt

... einfach um Zeilenumbrüche zu verwenden. Klar, es ist kein One-Liner mehr, aber realistisch gesehen war es vorher auch kein One-Liner. Wenn Sie dies innerhalb eines Skripts tun und sich Gedanken über das Einrücken machen (z. B. wenn Sie dies innerhalb einer Funktion ausführen), gibt es ein paar Workarounds, um dies noch gut zu machen, einschließlich, aber nicht beschränkt auf:

(echo 'task goes here' && cat todo.txt) > todo.txt
echo 'task goes here'$'\n'"$(cat todo.txt)" > todo.txt

Auch wenn Sie daran interessiert sind, ob ein Zeilenumbruch am Ende hinzugefügt wird todo.txtBenutze diese nicht. Nun, außer dem vorletzten. Das verwirrt nicht das Ende.


59
2017-12-19 18:57



Ich bekomme $ (...) überhaupt nicht. - SCL
Das könnte besser (oder überhaupt) mit doppelten Anführungszeichen anstelle von einzelnen funktionieren ... - ℝaphink
Will nicht das -e Konvertieren Sie auch Escapesequenzen in todo.txt? - mk12
Workarounds Ertrag -> cat: <Zieldateiname>: Eingabedatei ist Ausgabedatei ... - ingyhere
printf wäre plattformübergreifend sehr viel konsistenter und sollte in der Regel flüssiger arbeiten als echo -e - Peter Berg


Das moreutils habe ein nettes Werkzeug namens sponge:

echo "task goes here" | cat - todo.txt | sponge todo.txt

Es wird STDIN "aufsaugen" und dann in die Datei schreiben, was bedeutet, dass Sie sich keine Gedanken über temporäre Dateien machen müssen und sie verschieben müssen.

Du kannst bekommen moreutils mit vielen Linux-Distributionen, durch apt-get install moreutilsoder unter OS X mit Homebrewmit brew install moreutils.


26
2018-04-22 12:47





Sie können Vim im Ex-Modus verwenden:

ex -sc '1i|task goes here' -cx todo.txt
  1. 1 Wähle die erste Zeile aus

  2. i einfügen

  3. x speichern und schließen


5
2018-04-11 00:23





Sie können eine neue temporäre Datei erstellen.

echo "new task" > new_todo.txt
cat todo.txt >> new_todo.txt
rm todo.txt
mv new_todo.txt todo.txt

Sie könnten auch verwenden sed oder awk. Aber im Grunde passiert das Gleiche.


3
2018-02-17 03:26



Angenommen, Sie haben keinen Speicherplatz mehr auf der Festplatte new_todo.txt wird nur teilweise geschrieben. Ihre Lösung scheint die ursprüngliche Datei zu verlieren. - NPE
Wer hat keinen Speicherplatz mehr? ;-) Es ist nur ein einfaches Beispiel. - Keith
@Keith Jemand, der an einer VM arbeitet, die nicht erwartet hat, dass ein besonders großes virtuelles Laufwerk benötigt wird. Oder jemand, der eine große Datei bewegt. In jedem Fall ist das eigentliche Argument dagegen Verzeichnisberechtigungen; Wenn Sie keine Berechtigung zum Erstellen neuer Dateien im angegebenen Verzeichnis haben, ist der einzige Befehl, der erfolgreich in Ihrem Skript ausgeführt wird rm der ursprünglichen Datei. - Parthian Shot


Wenn die Textdatei klein genug ist, um in den Speicher zu passen, müssen Sie keine temporäre Datei erstellen, um sie zu ersetzen. Sie können alles in den Speicher laden und in die Datei zurückschreiben.

echo "$(echo 'task goes here' | cat - todo.txt)" > todo.txt

Es ist unmöglich, Zeilen am Anfang der Datei hinzuzufügen, ohne die gesamte Datei zu überschreiben.


3
2018-01-09 22:49



Nur um die offensichtliche Frage zu stellen: Wo ist das Zeichenlimit von Shell-Variablen? - nixda
Soweit mir bekannt ist, ist es nur durch den verfügbaren Speicherplatz begrenzt. Ich habe Variablen weit über 100 MB in den Speicher gefüllt. text=$(cat file). Achten Sie jedoch darauf, nur Text zu verwenden, da Shell-Variablen nicht binär sauber sind mywiki.wooledge.org/BashFAQ/058 - Rucent88


Sie können keinen Inhalt am Anfang einer Datei einfügen. Sie können nur vorhandenen Inhalt ersetzen oder Bytes nach dem aktuellen Dateiende anhängen.

Jede Lösung Ihrer Frage erfordert dann die Erstellung einer temporären Datei (oder eines Puffers) (im Speicher oder auf der Festplatte), die schließlich die ursprüngliche Datei überschreibt.

Seien Sie vorsichtig, dass Sie keine Daten verlieren, indem Sie die Originaldatei während der Erstellung der neuen Datei beibehalten, sollte das Dateisystem während des Prozesses voll sein. z.B:

cat <(echo task go there) todo.txt > todo.txt.new && mv todo.txt.new todo.txt

2
2018-02-17 06:25



Downvoters können gerne ihre Motivation erklären. Keine der verbleibenden Antworten, einschließlich der akzeptierten, widerspricht etwas in meiner Antwort. - jlliagre
Das ist schwer zu analysieren, da die <...> wie Klammern aussehen, was ich nicht annehme. Ein Leerzeichen zwischen dem <und dem (kann helfen? - dumbledad
Das funktioniert nicht für mich. echo HOME=\"/g/Users/timregan/\" | cat - 'F:\Program Files\Git\etc\profile' funktioniert aber cat <echo HOME=\"/g/Users/timregan/\" 'F:\Program Files\Git\etc\profile' gibt den Fehler "echo: Keine solche Datei oder Verzeichnis" - dumbledad
@ dumbledad Sie überschätzen meine Antwort. Es gibt nichts für Sie darin zu analysieren. Ein Raum zwischen den < und das ( würde die Syntax brechen. Versuchen cat <(echo HOME=\"/g/Users/timregan/\") 'F:\Program Files\Git\etc\profile' - jlliagre