Wie füge ich einen Text am Anfang einer Datei ein?

213

Bisher konnte ich herausfinden, wie eine Zeile am Anfang einer Datei hinzugefügt werden kann, aber genau das möchte ich nicht. Ich werde es an einem Beispiel zeigen

Dateiinhalt

some text at the beginning

Ergebnis

<added text> some text at the beginning

Es ist ähnlich, aber ich möchte keine neue Linie damit erstellen ...

Ich würde dies gerne tun, sedwenn möglich.

user219882
quelle
Arbeitet hier etwas für Sie? stackoverflow.com/questions/54365/… - Sie müssen nicht verwenden sed.
wkl

Antworten:

314

sed kann an einer Adresse arbeiten:

$ sed -i '1s/^/<added text> /' file

Was ist das Magische, das 1sSie bei jeder Antwort hier sehen? Leitungsadressierung! .

Möchten Sie <added text>die ersten 10 Zeilen hinzufügen ?

$ sed -i '1,10s/^/<added text> /' file

Oder Sie können verwenden Command Grouping:

$ { echo -n '<added text> '; cat file; } >file.new
$ mv file{.new,}
kev
quelle
67
Um tatsächlich eine neue Zeile einzufügen: sed -i '1s / ^ / <hinzugefügter Text> \ n /' Datei
jslatts
1
Warum -i verwenden? Auf Mann sagt es, dass es für Suffix ist. linux.die.net/man/1/sed
endrigoantonini
-i steht für In-Place. Sie können ein Suffix an -i anhängen, um eine Kopie zu erstellen, anstatt sie zu überschreiben. -i.new würde eine neue Datei erstellen, die mit .new endet, aber nur -i würde die Datei direkt bearbeiten.
Jay Kamat
3
Beachten Sie, dass das sed bei einer leeren Datei nicht funktioniert - afaict sed kann mit Eingaben der Länge 0 überhaupt nicht dazu gebracht werden, etwas zu tun.
Bis zum
2
Der Fehler dieser Lösung besteht darin, dass der Text nicht hinzugefügt wird, wenn die Datei leer ist.
DBedrenko
41

Wenn Sie eine Zeile am Anfang einer Datei hinzufügen möchten, müssen Sie \nam Ende der Zeichenfolge die beste Lösung oben hinzufügen .

Die beste Lösung fügt die Zeichenfolge hinzu, aber mit der Zeichenfolge wird keine Zeile am Ende einer Datei hinzugefügt.

sed -i '1s/^/your text\n/' file
Ali Reza Ebadat
quelle
27

Wenn die Datei nur eine Zeile enthält, können Sie Folgendes verwenden:

sed 's/^/insert this /' oldfile > newfile

Wenn es mehr als eine Zeile ist. einer von:

sed '1s/^/insert this /' oldfile > newfile
sed '1,1s/^/insert this /' oldfile > newfile

Ich habe letzteres eingefügt, damit Sie wissen, wie man Linienbereiche macht. Beide "ersetzen" die Startzeilenmarkierung in den betroffenen Zeilen durch den Text, den Sie einfügen möchten. Sie können auch (vorausgesetzt, Sie sedsind modern genug) Folgendes verwenden:

sed -i 'whatever command you choose' filename

In-Place-Bearbeitung durchführen.

paxdiablo
quelle
11

Sie können verwenden cat -

printf '%s' "some text at the beginning" | cat - filename
Lex
quelle
6
Dies würde nur den Text ausgeben, dem der Inhalt der Datei folgt, aber die Datei wird überhaupt nicht geändert.
Adaephon
Das ist eine gute Lösung, ich frage mich, warum es keine positiven Stimmen bekommen hat. Hier ist meins, mein guter Herr. Warum auch printf und kein einfaches Echo?
Ychaouche
1
@ychaouche - vermutlich, weil es keine tragbare Möglichkeit gibt, das echoHinzufügen einer neuen Zeile zu verhindern ?
Toby Speight
Ich habe versucht, dies in eine Datei zu leiten, indem ich > filean den Befehl "some text at the beginning"
angehängt habe.
2
printf '%s' "some text" | cat - filename > tmpfile && mv tmpfile filename
Luca
10

So fügen Sie nur eine neue Zeile ein:

sed '1i\\'

quelle
8

Unterschale verwenden:

echo "$(echo -n 'hello'; cat filename)" > filename
Nick Roz
quelle
5

Beachten Sie, dass unter OS X ein sed -i <pattern> fileFehler auftritt. Wenn Sie jedoch eine Sicherungserweiterung bereitstellen sed -i old <pattern> file, filewird diese beim Erstellen an Ort und Stelle geändert file.old. Sie können dann file.oldin Ihrem Skript löschen .

Curt Clifton
quelle
4
Oder sed -i '' Datei. Dann wird es einfach direkt bearbeitet und keine Backups erstellt.
Harv
Ich habe festgestellt, dass macOS sed möchte, dass ein Punkt bearbeitet wird, ohne ein Backup zu erstellen: sed -i. <Muster> Datei
Bryan
4

PROBLEM: Kennzeichnen Sie eine Datei oben in der Datei mit dem Basisnamen des übergeordneten Verzeichnisses.

Dh für

/mnt/Vancouver/Programming/file1

Markieren Sie die Oberseite file1mit Programming.

LÖSUNG 1 - Nicht leere Dateien:

bn=${PWD##*/}    ## bn: basename

sed -i '1s/^/'"$bn"'\n/' <file>

1s Platziert den Text in Zeile 1 der Datei.

LÖSUNG 2 - leere oder nicht leere Dateien:

Der sedobige Befehl schlägt bei leeren Dateien fehl. Hier ist eine Lösung, die auf /superuser/246837/how-do-i-add-text-to-the-beginning-of-a-file-in-bash/246841#246841 basiert

printf "${PWD##*/}\n" | cat - <file> > temp && mv -f temp <file>

Beachten Sie, dass der -Befehl in cat erforderlich ist (liest die Standardeingabe: siehe man catfür weitere Informationen). Hier, glaube ich, ist es notwendig, die Ausgabe der printf-Anweisung (nach STDIN) zu übernehmen und diese und die Datei auf temp zu setzen ... Siehe auch die Erklärung unten auf http://www.linfo.org/cat .html .

Ich -fhabe den mvBefehl auch hinzugefügt , um zu vermeiden, dass beim Überschreiben von Dateien nach Bestätigungen gefragt wird.

So verwenden Sie ein Verzeichnis:

for file in *; do printf "${PWD##*/}\n" | cat - $file > temp && mv -f temp $file; done

Beachten Sie auch, dass dadurch Pfade mit Leerzeichen unterbrochen werden. An anderer Stelle gibt es Lösungen (z. B. Dateiglobbing oderfind . -type f ... Lösungen vom Typ) für diese.

ADDENDUM: Betreff: Mein letzter Kommentar: Mit diesem Skript können Sie Verzeichnisse mit Leerzeichen in den Pfaden durchsuchen:

#!/bin/bash

## /programming/4638874/how-to-loop-through-a-directory-recursively-to-delete-files-with-certain-extensi

## To allow spaces in filenames,
##   at the top of the script include: IFS=$'\n'; set -f
##   at the end of the script include: unset IFS; set +f

IFS=$'\n'; set -f

# ----------------------------------------------------------------------------
# SET PATHS:

IN="/mnt/Vancouver/Programming/data/claws-test/corpus test/"

# /superuser/716001/how-can-i-get-files-with-numeric-names-using-ls-command

# FILES=$(find $IN -type f -regex ".*/[0-9]*")        ## recursive; numeric filenames only
FILES=$(find $IN -type f -regex ".*/[0-9 ]*")         ## recursive; numeric filenames only (may include spaces)

# echo '$FILES:'                                      ## single-quoted, (literally) prints: $FILES:
# echo "$FILES"                                       ## double-quoted, prints path/, filename (one per line)

# ----------------------------------------------------------------------------
# MAIN LOOP:

for f in $FILES
do

  # Tag top of file with basename of current dir:
  printf "[top] Tag: ${PWD##*/}\n\n" | cat - $f > temp && mv -f temp $f

  # Tag bottom of file with basename of current dir:
  printf "\n[bottom] Tag: ${PWD##*/}\n" >> $f
done

unset IFS; set +f
Victoria Stuart
quelle
3

Hallo mit Wagenrücklauf:

sed -i '1s/^/your text\n/' file
xck
quelle
3

So fügen Sie eine Zeile am Anfang der Datei hinzu:

sed -i '1iText to add\'
Solidsnack
quelle
Dies beinhaltet eine neue Zeile, die der Fragesteller ausdrücklich nicht möchte.
Toby Speight
Vielen Dank, dass Sie mir genau das gegeben haben, was ich brauche
FindOutIslamNow
3

Es gibt einen sehr einfachen Weg:

echo "your header" > headerFile.txt
cat yourFile >> headerFile.txt
Raphael Villas Boas
quelle
Au ... Entschuldigung, jetzt, da mir klar ist, dass Sie am Anfang eine neue Zeile hinzufügen wollten und nicht.
Raphael Villas Boas
Aber ich wollte eine neue Linie. Vielen Dank für den simplen Ansatz.
TheSatinKnight
3

Nur zum Spaß, hier ist eine Lösung, eddie nicht das Problem hat, nicht an einer leeren Datei zu arbeiten. Sie können es wie jede andere Antwort auf diese Frage in ein Shell-Skript einfügen.

ed Test <<EOF
a

.
0i
<added text>
.
1,+1 j
$ g/^$/d
wq
EOF

Das obige Skript fügt den einzufügenden Text in die erste Zeile ein und verbindet dann die erste und zweite Zeile. Um zu vermeiden, dass ed bei einem ungültigen Join bei einem Fehler beendet wird, wird zuerst eine leere Zeile am Ende der Datei erstellt und später entfernt, falls sie noch vorhanden ist.

Einschränkungen: Dieses Skript funktioniert nicht, wenn <added text>es genau einem einzelnen Punkt entspricht.

merlin2011
quelle
2

meine zwei Cent:

sed  -i '1i /path/of/file.sh' filename

Dies funktioniert auch dann, wenn die Zeichenfolge einen Schrägstrich enthält "/"

Vardhan
quelle
1
echo -n "text to insert " ;tac filename.txt| tac > newfilename.txt

Der erste tacleitet die Datei rückwärts weiter (letzte Zeile zuerst), sodass der "einzufügende Text" zuletzt angezeigt wird. Beim zweiten wird taces erneut umbrochen, sodass die eingefügte Zeile am Anfang steht und die Originaldatei in der ursprünglichen Reihenfolge vorliegt.

paulp
quelle
1
Können Sie bitte erklären, wie dies Tomas bei dem Problem helfen würde?
John Odom
tac | tac - so bilden sich nicht skalierbare Denkweisen :-(
Michael Shigorin
0

Eine andere Lösung mit Aliasen. Fügen Sie Ihrer init rc / env-Datei Folgendes hinzu:

addtail () { find . -type f ! -path "./.git/*" -exec sh -c "echo $@ >> {}" \; }
addhead () { find . -type f ! -path "./.git/*" -exec sh -c  "sed -i '1s/^/$@\n/' {}" \; }

Verwendung:

addtail "string to add at the beginning of file"
addtail "string to add at the end of file"
0x8BADF00D
quelle