Wie füge ich alle (Text-) Dateien eines Verzeichnisses zu einer zusammen?

89

Ich habe 14 Dateien, die alle Teile eines Textes sind. Ich möchte sie zu einem zusammenführen. Wie geht das?

Ivan
quelle

Antworten:

168

Dies ist technisch gesehen das, was cat("verketten") tun soll, obwohl die meisten Leute es nur für die Ausgabe von Dateien auf stdout verwenden. Wenn Sie ihm mehrere Dateinamen geben, werden alle nacheinander ausgegeben, und Sie können dies in eine neue Datei umleiten. Im Falle aller Dateien verwenden Sie einfach *(oder /path/to/directory/*wenn Sie nicht bereits im Verzeichnis sind) und Ihre Shell wird es auf alle Dateinamen erweitern

$ cat * > merged-file
Michael Mrozek
quelle
15
Beachten Sie, dass Ihr Befehl in Anführungszeichen wahrscheinlich nur das tut, was das Poster will, wenn die Nummerierung so gewählt ist, dass sich die Shell *in "natürlicher" Reihenfolge ausdehnt . Wenn Sie "file1.txt ... file9.txt ... file14.txt" haben, funktioniert dies nicht, da file1? .Txt zwischen file1.txt und file2.txt sortiert. Sie müssten sie in "file01.txt ... file09.txt ... file14.txt" umbenennen. Sagen echo *Sie, wenn Sie sich nicht sicher sind.
Warren Young
2
@Warren: Guter Punkt (oder Sie können zsh verwenden und seine numeric_glob_sortOption einstellen ).
Gilles
2
@ warren-young ein richtiger, nützlicher warnkommentar. In meinem Fall spielt die Reihenfolge jedoch keine Rolle (da Dateien nur einfache SQL-Anweisungen enthalten, in die Datensätze ohne Abhängigkeiten eingefügt werden).
Ivan
2
Achtung, wenn die Anzahl der Dateien ein bestimmtes Limit überschreitet, können Fehler auftreten wie - / bin / cat: Argumentliste zu lang
Nupur
1
@ ARA1307 Nur wenn die Datei bereits vorhanden ist. Andernfalls wird der Glob erweitert, bevor die Shell die Datei öffnet, in die geschrieben werden soll. Guter Punkt in dieser Situation
Michael Mrozek
25

Wenn sich Ihre Dateien nicht im selben Verzeichnis befinden, können Sie vor der Verkettung den Befehl find verwenden:

find /path/to/directory/ -name *.csv -print0 | xargs -0 -I file cat file > merged.file

Sehr nützlich, wenn Ihre Dateien bereits bestellt sind und Sie sie zusammenführen möchten, um sie zu analysieren.


Tragbarer:

find /path/to/directory/ -name *.csv -exec cat {} + > merged.file

Dadurch wird möglicherweise die Dateireihenfolge beibehalten oder nicht.

3nrique0
quelle
1
Dies ist der richtige Weg, wenn Sie viele Dateien haben. Sie vermeiden den Fehler "Argumentliste zu lang".
Мати Тернер
2
Sie benötigen -name "* .csv" anstelle von -name * .csv - ohne die Anführungszeichen, die fehlschlagen.
Peteris
Die Notwendigkeit von Anführungszeichen hängt von der Version des Befehls find ab, insbesondere in find und awk. Wenn Sie einen Mac verwenden, ist die Version beider Programme etwas veraltet. Bisher funktionierte es auf Ubuntu, Fedora, Debian und CentOS reibungslos ohne die Anführungszeichen
3nrique0
Ich würde erwarten, dass die nicht zitierte Version funktioniert, wenn sich im aktuellen Verzeichnis keine Dateien befinden, die dem Muster entsprechen "*.csv", da die Shell dann das Literal *an übergeben würde find.
RJHunter
9

Der Befehl

$ cat * > merged-file

Tatsächlich hat dies den unerwünschten Nebeneffekt, dass "zusammengeführte Datei" in die Verkettung einbezogen wird und eine weggelaufene Datei erstellt wird. Um dies zu umgehen, schreiben Sie entweder die zusammengeführte Datei in ein anderes Verzeichnis.

$ cat * > ../merged-file

oder verwenden Sie eine Musterübereinstimmung, bei der die zusammengeführte Datei ignoriert wird.

$ cat *.txt > merged-file
Christopher Jones
quelle
14
cat * > merged-filefunktioniert gut. Globs werden verarbeitet, bevor die Datei erstellt wird. Falls merged-filebereits vorhanden, erkennt cat(zumindest meine), dass es sich um die Ausgabedatei handelt, und lehnt es ab, sie zu lesen. WENN die Datei bereits existiert UND Sie die Umleitung später in der Pipeline haben, kann sie das offensichtlich nicht, und erst dann erhalten Sie die außer Kontrolle geratene Datei.
Kevin
catkann nicht erkennen, ob es sich bei der Datei um die Ausgabe handelt. Die Umleitung erfolgt in der Shell. catdruckt nur auf stdout.
Bfontaine
8

Wie die anderen von hier sagen ... können Sie verwenden cat

Sagen wir, Sie haben:

~/file01
~/file02
~/file03
~/file04
~/fileA
~/fileB
~/fileC
~/fileD

Und du willst nur file01zu file03und fileAzu fileC:

cat ~/file01 ~/file02 ~/file03 ~/fileA ~/fileB ~/fileC > merged-file

Oder verwenden Sie die Klammererweiterung:

cat ~/file0{1..3} ~/file{A..C} > merged-file

Oder mit einer schickeren Klammererweiterung:

cat ~/file{0{1..3},{A..C}} > merged-file

Oder Sie können forSchleife verwenden:

for i in file0{1..3} file{A..C}; do cat ~/"$i"; done > merged-file
Florin Idita
quelle
1
Beachten Sie, dass die Zeichenfolge [01-03]nicht als Globbing-Muster funktioniert.
Kusalananda
0

Sie können das patterneiner Datei angeben und dann alle wie folgt zusammenführen:

cat *pattern* >> mergedfile
user182845
quelle
0

Eine andere 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 merge.txt geschrieben wird (nicht wmerge.txt!). Sie können w "merge.txt" verwenden, um Verwechslungen mit dem Dateinamen zu vermeiden, und -n für die stille Ausgabe.

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 in geschweiften Klammern angeben:

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