Verketten von Dateien und Einfügen einer neuen Zeile zwischen Dateien


127

Ich habe mehrere Dateien, mit denen ich mich befassen möchte cat. Sagen wir

File1.txt 
foo

File2.txt
bar

File3.txt
qux

Ich möchte mich darauf konzentrieren, dass die endgültige Datei wie folgt aussieht:

foo

bar

qux

Stattdessen mit üblich cat File*.txt > finalfile.txt

foo
bar 
qux

Was ist der richtige Weg, um es zu tun?


Antworten:


120

Du kannst tun:

for f in *.txt; do (cat "${f}"; echo) >> finalfile.txt; done

Stellen Sie sicher, dass die Datei finalfile.txtnicht vorhanden ist, bevor Sie den obigen Befehl ausführen.

Wenn Sie verwenden dürfen, können awkSie Folgendes tun:

awk 'FNR==1{print ""}1' *.txt > finalfile.txt

10
AWK '{print $0}' *.txt
Timger

7
Dies hat den deutlichen Fehler, dass es entweder am Ende (von der ersten Alternative) oder am Anfang (von der zweiten Alternative) leere Zeilen geben wird. Sie können sich jedoch leicht dagegen schützen awk 'FNR==1 && NR > 1 ...'.
Tripleee

5
Wenn Sie >finalfile.txtnach dem setzen done, können Sie überschreiben anstatt anzuhängen, wodurch die Anforderung beseitigt wird, sicherzustellen, dass die Datei vor der Schleife fehlt oder leer ist.
Tripleee

53

Wenn Sie nur wenige Dateien haben, die Sie auflisten können, können Sie die Prozessersetzung in Bash verwenden und zwischen jedem Dateipaar eine neue Zeile einfügen:

cat File1.txt <(echo) File2.txt <(echo) File3.txt > finalfile.txt

1
Wunderschönen! Vielen Dank.
Bob Kocisko

Dies funktionierte gut für mich, damit meine Letsencrypt-Zertifikate PEM-Dateien erstellen konnten.
Leeman24

35

Wenn ich es tun würde, würde ich sed verwenden:

sed -e '$s/$/\n/' -s *.txt > finalfile.txt

In diesem sed-Muster hat $ zwei Bedeutungen: Erstens entspricht es nur der letzten Zeilennummer (als Bereich von Zeilen, auf die ein Muster angewendet werden soll) und zweitens dem Zeilenende im Substitutionsmuster.

Wenn Ihre Version von sed keine hat -s(Eingabedateien separat verarbeiten), können Sie dies alles als Schleife ausführen:

for f in *.txt ; do sed -e '$s/$/\n/' $f ; done > finalfile.txt

3
Oder in GNU sed:sed -s '$G' *.txt > finalfile.txt
Ruud Helderman

Nur ein Stream! Dies sollte die akzeptierte Antwort sein!
Yassine ElBadaoui

Seid vorsichtig, ich habe gerade meinen PC abgestürzt, weil ich findanstelle von verwendet habe *.txt, was bedeutete, dass die Datei an sich selbst angehängt wurde!
Xerus

11

Sie können es verwenden, xargswenn Sie möchten, aber die Hauptidee ist immer noch dieselbe:

find *.txt | xargs -I{} sh -c "cat {}; echo ''" > finalfile.txt

1
Vielen Dank. Ich finde es xargsviel einfacher zu benutzen als Loops in Bash.
RawwrBag

9

Dies funktioniert in Bash:

for f in *.txt; do cat $f; echo; done

Im Gegensatz zu Antworten mit >>(Anhängen) kann die Ausgabe dieses Befehls in andere Programme geleitet werden.

Beispiele:

  • for f in File*.txt; do cat $f; echo; done > finalfile.txt
  • (for ... done) > finalfile.txt (Parens sind optional)
  • for ... done | less (Rohrleitungen in weniger)
  • for ... done | head -n -1 (Dadurch wird die nachfolgende Leerzeile entfernt.)

7

So habe ich es gerade unter OsX 10.10.3 gemacht

for f in *.txt; do (cat $f; echo '') >> fullData.txt; done

da der einfache 'echo'-Befehl ohne Parameter in keinen neuen Zeilen eingefügt wurde.


Dadurch wird die Zeichenfolge am Ende der Datei platziert. Wie kann ich es zwischen die einzelnen Dateien einfügen ?
Onassar

3

In Python verkettet sich dies mit Leerzeilen zwischen Dateien (dies ,unterdrückt das Hinzufügen einer zusätzlichen nachgestellten Leerzeile):

print '\n'.join(open(f).read() for f in filenames),

Hier ist der hässliche Python-Einzeiler, der von der Shell aufgerufen werden kann und die Ausgabe in eine Datei druckt:

python -c "from sys import argv; print '\n'.join(open(f).read() for f in argv[1:])," File*.txt > finalfile.txt
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.