So hängen Sie den Inhalt mehrerer Dateien an eine Datei an

173

Ich möchte den Inhalt von fünf Dateien unverändert in eine Datei kopieren. Ich habe versucht, es mit cp für jede Datei zu tun. Dadurch wird jedoch der aus der vorherigen Datei kopierte Inhalt überschrieben. Ich habe es auch versucht

paste -d "\n" 1.txt 0.txt

und es hat nicht funktioniert.

Ich möchte, dass mein Skript die neue Zeile am Ende jeder Textdatei hinzufügt.

z.B. Dateien 1.txt, 2.txt, 3.txt. Geben Sie den Inhalt von 1,2,3 in 0.txt ein

Wie mache ich es ?

Dampf
quelle

Antworten:

307

Sie benötigen den catBefehl (kurz für verketten) mit Shell Redirection ( >) in Ihre Ausgabedatei

cat 1.txt 2.txt 3.txt > 0.txt
radikal7
quelle
8
sollte >> richtig sein? und warum steht vor dem gesamten Text in meiner 0.txt-Datei eine neue Zeile?
Steam
1
Wollten Sie den Inhalt von 0.txt beibehalten?
sehe
13
@blasto es kommt darauf an. Sie würden verwenden >>, um eine Datei an eine andere anzuhängen , wobei die Ausgabedatei mit den Anweisungen > überschrieben wird . Gibt es für die neue Zeile eine neue Zeile als erstes Zeichen in der Datei 1.txt? Sie können herausfinden, od -cob das erste Zeichen a ist \n.
radikal7
1
@ radikal7 Danke. Eigentlich sind meine Dateien wie foo_1, foo_2, foo_3. Ich habe versucht, Ihren Code als - cat "$ filename _" {1,2,3} ". Txt" zu ändern, aber es hat nicht funktioniert.
Steam
1
@blasto Du gehst definitiv in die richtige Richtung. Bash akzeptiert auf jeden Fall das Formular {...}für den Dateinamenabgleich. Vielleicht haben die Anführungszeichen die Dinge in Ihrem Skript etwas durcheinander gebracht? Ich versuche immer, mit solchen Dingen lsin einer Shell zu arbeiten. Wenn ich den Befehl richtig verstanden habe, schneide ich ihn einfach aus und füge ihn so wie er ist in ein Skript ein. Möglicherweise ist die -xOption auch in Ihren Skripten hilfreich. Sie gibt die erweiterten Befehle im Skript vor der Ausführung wieder.
radikal7
97

Eine andere Option für diejenigen unter Ihnen, die immer noch wie ich über diesen Beitrag stolpern, ist die Verwendung von find -exec:

find . -type f -name '*.txt' -exec cat {} + >> output.file

In meinem Fall brauchte ich eine robustere Option, die mehrere Unterverzeichnisse durchsucht, also entschied ich mich für die Verwendung find. Brechen sie ab:

find .

Suchen Sie im aktuellen Arbeitsverzeichnis.

-type f

Interessiert sich nur für Dateien, nicht für Verzeichnisse usw.

-name '*.txt'

Reduzieren Sie die Ergebnismenge nach Namen

-exec cat {} +

Führen Sie den Befehl cat für jedes Ergebnis aus. "+" bedeutet, dass nur 1 Instanz von erzeugt catwird (thx @gniourf_gniourf)

 >> output.file

Hängen Sie, wie in anderen Antworten erläutert, den Inhalt der Katze an das Ende einer Ausgabedatei an.

mopo922
quelle
10
Diese Antwort enthält viele Mängel. Zunächst muss der Platzhalter *.txtin Anführungszeichen gesetzt werden (andernfalls ist der gesamte findBefehl, wie geschrieben, nutzlos). Ein weiterer Fehler ergibt sich aus einem groben Missverständnis: Der Befehl, der ausgeführt wird cat >> 0.txt {} , ist nicht , aber cat {}. Ihr Befehl entspricht in der Tat { find . -type f -name *.txt -exec cat '{}' \; ; } >> 0.txt(ich habe eine Gruppierung hinzugefügt, damit Sie erkennen, was wirklich passiert). Ein weiterer Fehler besteht darin, dass finddie Datei gefunden 0.txtwird und catsich beschwert, dass die Eingabedatei eine Ausgabedatei ist .
gniourf_gniourf
Danke für die Korrekturen. Mein Fall war ein bisschen anders und ich hatte nicht an einige dieser Fallstricke gedacht, die auf diesen Fall angewendet wurden.
Mopo922
Sie sollten >> output.fileam Ende Ihres Befehls setzen, damit Sie niemanden (einschließlich sich selbst) zum Denken findanregen, das cat {} >> output.filefür jede gefundene Datei ausgeführt wird.
gniourf_gniourf
Fangen an richtig gut auszusehen! Ein letzter Vorschlag: Verwenden Sie -exec cat {} +statt -exec cat {} \;, damit nur eine Instanz von catmit mehreren Argumenten erzeugt wird ( +wird von POSIX angegeben ).
gniourf_gniourf
3
Gute Antwort und ein Wort der Warnung - ich find . -type f -exec cat {} + >> outputfile.txthabe meine geändert in: und konnte nicht herausfinden, warum meine Ausgabedatei nicht aufhören würde, in die Gigs hineinzuwachsen, obwohl das Verzeichnis nur 50 Megabyte groß war. Es war, weil ich die Datei outputfile.txt immer wieder an mich selbst angehängt habe! Stellen Sie also sicher, dass Sie diese Datei korrekt benennen, oder legen Sie sie vollständig in einem anderen Verzeichnis ab, um dies zu vermeiden.
Thisisstackoverflow
43

Wenn Sie einen bestimmten Ausgabetyp haben, gehen Sie wie folgt vor

cat /path/to/files/*.txt >> finalout.txt
Eswar Yaganti
quelle
1
Beachten Sie jedoch, dass Sie die Möglichkeit verlieren, die Zusammenführungsreihenfolge beizubehalten. Dies kann sich auf Sie auswirken, wenn Sie Ihre Dateien benannt haben, z. file_1,, file_2file_11, Aufgrund der natürlichen Reihenfolge, in der Dateien sortiert werden.
Emix
16

Wenn sich alle Ihre Dateien in einem einzigen Verzeichnis befinden, können Sie dies einfach tun

cat * > 0.txt

Dateien 1.txt, 2.txt, .. gehen in 0.txt

Pooja
quelle
Bereits von Eswar beantwortet. Beachten Sie jedoch, dass Sie die Möglichkeit verlieren, die Zusammenführungsreihenfolge beizubehalten. Dies kann sich auf Sie auswirken, wenn Sie Ihre Dateien benannt haben, z. file_1,, file_2file_11, Aufgrund der natürlichen Reihenfolge, in der Dateien sortiert werden.
Emix
10
for i in {1..3}; do cat "$i.txt" >> 0.txt; done

Ich habe diese Seite gefunden, weil ich 952 Dateien zu einer zusammenfügen musste. Ich fand, dass dies viel besser funktioniert, wenn Sie viele Dateien haben. Dies führt eine Schleife für so viele Zahlen durch, wie Sie benötigen, und katzen Sie jede mit >>, um sie an das Ende von 0.txt anzuhängen.

Freddythunder
quelle
Sie könnten die Klammererweiterung in Bash verwenden, um cat {1,2,3} .txt >> 0.txt
mcheema
9

Wenn alle Ihre Dateien ähnlich benannt sind, können Sie einfach Folgendes tun:

cat *.log >> output.log
AeaRy
quelle
5

Eine weitere Option ist sed:

sed r 1.txt 2.txt 3.txt > merge.txt 

Oder...

sed h 1.txt 2.txt 3.txt > merge.txt 

Oder...

sed -n p 1.txt 2.txt 3.txt > merge.txt # -n is mandatory here

Oder ohne Weiterleitung ...

sed wmerge.txt 1.txt 2.txt 3.txt

Beachten Sie, dass in der letzten Zeile auch geschrieben wird merge.txt(nicht wmerge.txt!). Sie können verwenden w"merge.txt", um Verwechslungen mit dem Dateinamen zu vermeiden, und-n um eine stille Ausgabe zu ermöglichen.

Natürlich können Sie die Dateiliste auch mit Platzhaltern kürzen. Beispielsweise können Sie bei nummerierten Dateien wie in den obigen Beispielen den Bereich mit geschweiften Klammern wie folgt angeben:

sed -n w"merge.txt" {1..3}.txt
Fran
quelle
4

Wenn Ihre Dateien Header enthalten und Sie diese in der Ausgabedatei entfernen möchten, können Sie Folgendes verwenden:

for f in `ls *.txt`; do sed '2,$!d' $f >> 0.out; done
brunocrt
quelle
3

Wenn die Originaldatei nicht druckbare Zeichen enthält, gehen diese bei Verwendung des Befehls cat verloren. Mit 'cat -v' werden die nicht druckbaren Zeichen in sichtbare Zeichenfolgen konvertiert, aber die Ausgabedatei enthält immer noch nicht die tatsächlichen nicht druckbaren Zeichen in der Originaldatei. Bei einer kleinen Anzahl von Dateien kann eine Alternative darin bestehen, die erste Datei in einem Editor (z. B. vim) zu öffnen, der nicht druckbare Zeichen verarbeitet. Manövrieren Sie dann zum Ende der Datei und geben Sie ": r second_file_name" ein. Dadurch wird die zweite Datei eingezogen, einschließlich nicht druckbarer Zeichen. Das gleiche könnte für zusätzliche Dateien gemacht werden. Wenn alle Dateien eingelesen wurden, geben Sie ": w" ein. Das Endergebnis ist, dass die erste Datei nun das enthält, was sie ursprünglich getan hat, sowie den Inhalt der eingelesenen Dateien.

BACooper
quelle
Dies ist nicht sehr skriptfähig.
FKEinternet
1

Wenn Sie den Inhalt von 3 Dateien an eine Datei anhängen möchten, ist der folgende Befehl eine gute Wahl:

cat file1 file2 file3 | tee -a file4 > /dev/null

Es wird den Inhalt aller Dateien in Datei4 kombinieren und die Konsolenausgabe an senden /dev/null.

Ajit K'sagar
quelle