Bagaimana cara menggabungkan semua file (teks) dalam direktori menjadi satu?

89

Saya punya 14 file yang semuanya menjadi bagian dari satu teks. Saya ingin menggabungkan mereka menjadi satu. Bagaimana cara melakukannya?

Ivan
sumber

Jawaban:

168

Secara teknis inilah yang seharusnya cat("digabungkan") dilakukan, walaupun kebanyakan orang hanya menggunakannya untuk menghasilkan file ke stdout. Jika Anda memberikan beberapa nama file, ia akan menampilkan semuanya secara berurutan, dan kemudian Anda dapat mengarahkannya ke file baru; dalam hal semua file cukup gunakan *(atau /path/to/directory/*jika Anda belum berada di direktori) dan shell Anda akan memperluasnya ke semua nama file

$ cat * > merged-file
Michael Mrozek
sumber
15
Berhati-hatilah karena perintah Anda yang dikutip mungkin hanya akan melakukan apa yang diinginkan poster jika diberi nomor sedemikian rupa sehingga shell mengembang *dalam urutan "alami". Jika Anda memiliki "file1.txt ... file9.txt ... file14.txt" itu tidak akan berfungsi karena file1? .Txt akan mengurutkan antara file1.txt dan file2.txt. Anda harus mengubah nama mereka menjadi "file01.txt ... file09.txt ... file14.txt". Katakan echo *jika Anda tidak yakin.
Warren Young
2
@ Warren: poin bagus (atau Anda dapat menggunakan zsh dan mengatur numeric_glob_sortopsinya).
Gilles
2
@ warren-young komentar peringatan yang benar dan berguna. Tetapi dalam kasus saya yang sebenarnya, urutan tidak membuat perbedaan (karena file hanya berisi pernyataan SQL sederhana yang memasukkan catatan data yang tidak memiliki dependensi).
Ivan
2
Hati-hati, jika jumlah file melebihi batas tertentu, Anda dapat menjalankan kesalahan seperti - / bin / cat: Daftar argumen terlalu panjang
Nupur
1
@ ARA1307 Hanya jika file sudah ada; kalau tidak glob akan diperluas sebelum shell membuka file untuk menulisnya. Poin bagus dalam situasi itu
Michael Mrozek
25

Jika file Anda tidak berada di direktori yang sama, Anda dapat menggunakan perintah find sebelum concatenation:

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

Sangat berguna ketika file Anda sudah dipesan dan Anda ingin menggabungkannya untuk menganalisisnya.


Lebih mudah dibawa:

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

Ini mungkin atau mungkin tidak mempertahankan pesanan file.

3nrique0
sumber
1
Ini adalah cara untuk pergi jika Anda memiliki banyak file. Anda menghindari kesalahan "daftar argumen terlalu panjang".
Мати Тернер
2
Anda perlu -nama "* .csv" bukan -nama * .csv - tanpa tanda kutip, gagal.
Peteris
Kebutuhan untuk mengutip tergantung pada versi perintah find, khususnya dalam find dan awk, itu masalah ketika Anda menggunakan mac, versi kedua program agak lama. Sejauh ini di ubuntu, fedora, debian dan CentOS berfungsi dengan lancar tanpa tanda kutip
3nrique0
Saya berharap versi yang tidak dikutip berfungsi ketika tidak ada file di direktori saat ini yang cocok dengan pola "*.csv", karena shell kemudian akan meneruskan literal *ke find.
RJHunter
9

Perintah

$ cat * > merged-file

sebenarnya memiliki efek samping yang tidak diinginkan dengan memasukkan 'file yang digabungkan' dalam rangkaian, membuat file run-away. Untuk menyelesaikan ini, baik menulis file yang digabungkan ke direktori yang berbeda;

$ cat * > ../merged-file

atau menggunakan pencocokan pola yang akan mengabaikan file yang digabungkan;

$ cat *.txt > merged-file
Christopher Jones
sumber
14
cat * > merged-filebekerja dengan baik. Gumpalan diproses sebelum file dibuat. Jika merged-filesudah ada, cat(setidaknya milik saya) akan mendeteksi bahwa itu adalah file output dan menolak untuk membacanya. JIKA file tersebut sudah ada DAN Anda memiliki pengalihan nanti di dalam pipa, maka jelas tidak bisa melakukan itu, maka kemudian dan hanya Anda mendapatkan file runaway.
Kevin
cattidak memiliki cara untuk mendeteksi apakah file tersebut adalah file output. Pengalihan terjadi di shell; cathanya mencetak pada stdout.
bfontaine
8

Seperti yang lain dari sini katakan ... Anda dapat menggunakan cat

Katakanlah Anda memiliki:

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

Dan Anda ingin hanya file01untuk file03dan fileAuntuk fileC:

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

Atau, menggunakan ekspansi brace:

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

Atau, menggunakan ekspansi brancier yang lebih menarik:

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

Atau Anda dapat menggunakan forloop:

for i in file0{1..3} file{A..C}; do cat ~/"$i"; done > merged-file
Florin Idita
sumber
1
Perhatikan bahwa string [01-03]tidak akan berfungsi sebagai pola globbing.
Kusalananda
0

Anda dapat menentukan patternfile kemudian menggabungkan semuanya sebagai berikut:

cat *pattern* >> mergedfile
pengguna182845
sumber
0

Pilihan lain adalah sed:

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

Atau...

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

Atau...

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

Atau tanpa pengalihan ...

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

Perhatikan bahwa baris terakhir tulis juga merge.txt (bukan wmerge.txt!). Anda dapat menggunakan w "merge.txt" untuk menghindari kebingungan dengan nama file, dan -n untuk output diam.

Tentu saja, Anda juga dapat mempersingkat daftar file dengan wildcard. Misalnya, dalam kasus file bernomor seperti dalam contoh di atas, Anda dapat menentukan rentang dengan kawat gigi dengan cara ini:

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