Menggabungkan banyak file teks menjadi satu file di Bash

305

Apa cara tercepat dan paling pragmatis untuk menggabungkan semua file * .txt dalam direktori menjadi satu file teks besar?

Saat ini saya menggunakan windows dengan cygwin sehingga saya memiliki akses ke BASH.

Perintah shell Windows akan menyenangkan juga, tetapi saya ragu ada satu.

Yada
sumber

Jawaban:

537

Ini menambahkan output ke all.txt

cat *.txt >> all.txt

Ini menimpa semua.txt

cat *.txt > all.txt
Robert Greiner
sumber
30
Anda mungkin mengalami masalah di mana ia kucing all.txt ke all.txt ... Saya memiliki masalah ini dengan grep kadang-kadang, tidak yakin apakah kucing memiliki perilaku yang sama.
rmeador
8
@ rmeador ya, itu benar, jika all.txt sudah ada, Anda akan memiliki masalah ini. Masalah ini diselesaikan dengan memberikan file output dengan ekstensi yang berbeda, atau memindahkan all.txt ke folder yang berbeda.
Robert Greiner
2
cat * .txt >> tmp; mv tmp all.txt (dan pastikan all.txt tidak ada sebelumnya)
Renaud
16
Saya mendapatkan "Daftar argumen terlalu lama" - kira itu tidak dapat menangani 40.000+ file.
Matt
32
Hindari daftar argumen terlalu lama dengan:echo *.txt | xargs cat > all.txt
5heikki
145

Ingat saja, untuk semua solusi yang diberikan sejauh ini, shell memutuskan urutan di mana file-file tersebut digabungkan. Untuk Bash, IIRC, itu urutan alfabet. Jika urutannya penting, Anda harus memberi nama file dengan tepat (01file.txt, 02file.txt, dll ...) atau tentukan setiap file dalam urutan yang Anda inginkan.

$ cat file1 file2 file3 file4 file5 file6 > out.txt
Chinmay Kanchi
sumber
33

Perintah Windows shell typedapat melakukan ini:

type *.txt >outputfile

Ketik typeperintah juga menulis nama file ke stderr, yang tidak ditangkap oleh >operator pengalihan (tetapi akan muncul di konsol).

Greg Hewgill
sumber
2
Perlu diketahui bahwa jika Anda meletakkan file output di direktori yang sama dengan file asli itu akan menyebabkan duplikasi karena itu juga akan menggabungkan file output baru dua kali.
CathalMF
26

Anda dapat menggunakan shell Windows copyuntuk menggabungkan file.

C:\> copy *.txt outputfile

Dari bantuan:

Untuk menambahkan file, tentukan satu file untuk tujuan, tetapi beberapa file untuk sumber (menggunakan wildcard atau format file1 + file2 + file3).

Carl Norum
sumber
Ini sebagai solusi terbersih IMHO tanpa efek samping yang pemula bisa tersandung sayangnya tidak cukup dihargai :-(
Grmpfhmbl
OP meminta Bash.
Big Rich
2
Apakah Anda membaca pertanyaannya? "Perintah shell Windows juga akan menyenangkan ..."
Carl Norum
8

Hati-hati, karena tidak ada metode ini yang berfungsi dengan sejumlah besar file. Secara pribadi, saya menggunakan baris ini:

for i in $(ls | grep ".txt");do cat $i >> output.txt;done

EDIT: Seperti yang dikatakan seseorang di komentar, Anda dapat mengganti $(ls | grep ".txt") dengan$(ls *.txt)

EDIT: terima kasih kepada keahlian @gnourf_gnourf, penggunaan glob adalah cara yang benar untuk beralih pada file dalam direktori. Akibatnya, ekspresi menghujat seperti $(ls | grep ".txt")harus diganti oleh *.txt(lihat artikel di sini ).

Solusi yang bagus

for i in *.txt;do cat $i >> output.txt;done
Jacobe2169
sumber
1
Mengapa tidak for i in $(ls *.txt);do cat $i >> output.txt;done?
streamofstars
2
Tautan Parsing Wajib , bersama dengan downvote (dan Anda layak mendapatkan lebih dari satu downvote, karena ls | grepmerupakan antipattern yang sangat buruk).
gniourf_gniourf
Mendapat upvote dari saya karena memungkinkan untuk pengujian / operasi sewenang-wenang dengan nama file sebelum output dan itu cepat dan mudah dan bagus untuk latihan. (Dalam kasus saya, saya ingin: untuk saya di *; lakukan echo -e "\ n $ i: \ n"; cat $ 1; selesai)
Nathan Chappell
Bukankah ls *.txtgagal jika ada terlalu banyak file (daftar argumen kesalahan terlalu panjang)?
Rafael Almeida
6

cara paling pragmatis dengan shell adalah perintah cat. cara lain termasuk,

awk '1' *.txt > all.txt
perl -ne 'print;' *.txt > all.txt
ghostdog74
sumber
1
Ini harus menjadi jawaban yang benar untuk sebagian besar keadaan. Jika ada file teks tanpa baris baru kosong, menggunakan semua catmetode di atas akan menyatukan baris terakhir dan baris pertama dari file yang berdekatan.
mootmoot
6

Bagaimana dengan pendekatan ini?

find . -type f -name '*.txt' -exec cat {} + >> output.txt
GPrathap
sumber
Sejak OP mengatakan file-file tersebut dalam direktori yang sama, Anda mungkin perlu menambahkan -maxdepth 1ke findperintah.
codeforester
1
Bekerja sangat baik dengan sejumlah besar file, di mana pendekatan balasan yang diterima gagal
amine
ah aku berharap aku tahu apa ini plus dan double redirect menandakan ...
hello_earth
Ini seharusnya jawaban yang benar. Ini akan bekerja dengan baik dalam skrip shell. Berikut adalah metode serupa jika Anda ingin keluaran diurutkan:sort -u --output="$OUTPUT_FILE" --files0-from=- < <(find "$DIRECTORY_NAME" -maxdepth 1 -type f -name '*.txt' -print0)
steveH
3
type [source folder]\*.[File extension] > [destination folder]\[file name].[File extension]

Sebagai contoh:

type C:\*.txt > C:\1\all.txt

Itu akan mengambil semua file txt di folder C: \ dan menyimpannya di folder C: \ 1 dengan nama all.txt

Atau

type [source folder]\* > [destination folder]\[file name].[File extension]

Sebagai contoh:

type C:\* > C:\1\all.txt

Itu akan mengambil semua file yang ada di folder dan meletakkan Konten di sana di C: \ 1 \ all.txt

Ori
sumber
0

Anda bisa melakukan ini: cat [directory_path]/**/*.[h,m] > test.txt

jika Anda menggunakan {}untuk menyertakan ekstensi file yang ingin Anda temukan, ada masalah urutan.

Michael-zhang
sumber
0

Ketika Anda mengalami masalah di mana ia menjadi all.txt ke all.txt, Anda dapat mencoba memeriksa semua.txt ada atau tidak, jika ada, hapus

Seperti ini:

[ -e $"all.txt" ] && rm $"all.txt"

Leo
sumber
cat *.txt > all.txt >perintah menimpa semua.txt jika ada, >>menambah data ke file yang ada
Oleg Bondarenko
-4

semua itu jahat ....

ls | grep *.txt | while read file; do cat $file >> ./output.txt; done;

hal yang mudah.

kSiR
sumber
6
Eeek! Jangan lakukan itu. Dofind . -iname "*.txt" -maxdepth 1 -exec cat {} >> out.txt \;
Chinmay Kanchi