Ghép nhiều tệp văn bản thành một tệp duy nhất trong Bash


305

Cách nhanh nhất và thực tế nhất để kết hợp tất cả tệp * .txt trong một thư mục thành một tệp văn bản lớn là gì?

Hiện tại tôi đang sử dụng windows với cygwin vì vậy tôi có quyền truy cập vào BASH.

Lệnh Windows shell cũng sẽ tốt nhưng tôi nghi ngờ có một.

Câu trả lời:


537

Điều này nối thêm đầu ra cho all.txt

cat *.txt >> all.txt

Điều này ghi đè all.txt

cat *.txt > all.txt

30
bạn có thể gặp phải một vấn đề trong đó nó biến all.txt thành all.txt ... Đôi khi tôi gặp vấn đề này với grep, không chắc mèo có hành vi tương tự không.
rmeador

8
@rmeador có, đó là sự thật, nếu all.txt đã tồn tại, bạn sẽ gặp vấn đề này. Vấn đề này được giải quyết bằng cách cung cấp tệp đầu ra với một phần mở rộng khác hoặc di chuyển all.txt sang một thư mục khác.
Robert Greiner

2
mèo * .txt >> tmp; mv tmp all.txt (và đảm bảo rằng all.txt không tồn tại trước đó)
Đổi mới

16
Tôi nhận được "Danh sách đối số quá dài" - đoán nó không thể xử lý hơn 40.000 tệp.
Matt

32
Tránh danh sách đối số quá dài với:echo *.txt | xargs cat > all.txt
5heikki

145

Chỉ cần nhớ, đối với tất cả các giải pháp được đưa ra cho đến nay, shell quyết định thứ tự các tệp được nối. Đối với Bash, IIRC, đó là thứ tự chữ cái. Nếu thứ tự là quan trọng, bạn nên đặt tên cho các tệp một cách thích hợp (01file.txt, 02file.txt, v.v.) hoặc chỉ định từng tệp theo thứ tự bạn muốn nó được nối.

$ cat file1 file2 file3 file4 file5 file6 > out.txt

33

Lệnh shell Windows typecó thể làm điều này:

type *.txt >outputfile

typeLệnh type cũng ghi tên tệp vào stderr, không được bắt bởi >toán tử chuyển hướng (nhưng sẽ hiển thị trên bàn điều khiển).


2
Chỉ cần lưu ý rằng nếu bạn đặt tệp đầu ra vào cùng thư mục với tệp gốc, nó sẽ gây ra sự trùng lặp vì nó cũng sẽ kết hợp tệp đầu ra mới hai lần.
CathalMF

26

Bạn có thể sử dụng Windows shell copyđể nối các tệp.

C:\> copy *.txt outputfile

Từ sự giúp đỡ:

Để chắp thêm tệp, chỉ định một tệp cho đích, nhưng nhiều tệp cho nguồn (sử dụng ký tự đại diện hoặc định dạng tệp1 + tệp2 + tệp3).


Đây là giải pháp sạch nhất IMHO về cơ bản không có tác dụng phụ mà người mới bắt đầu có thể gặp phải không may không được đánh giá cao :-(
Grmpfhmbl

OP yêu cầu Bash.
Big Rich

2
Bạn đã đọc câu hỏi? "Lệnh Windows shell cũng sẽ rất tuyệt ..."
Carl Norum

8

Hãy cẩn thận, vì không có phương pháp nào trong số này hoạt động với số lượng lớn tệp. Cá nhân, tôi đã sử dụng dòng này:

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

EDIT: Như ai đó đã nói trong các bình luận, bạn có thể thay thế $(ls | grep ".txt")bằng$(ls *.txt)

EDIT: nhờ chuyên môn @gnourf_gnourf, việc sử dụng toàn cầu là cách chính xác để lặp lại các tệp trong một thư mục. Do đó, các biểu thức báng bổ như thế $(ls | grep ".txt")phải được thay thế bằng *.txt(xem bài viết ở đây ).

Giải pháp tốt

for i in *.txt;do cat $i >> output.txt;done

1
Tại sao không for i in $(ls *.txt);do cat $i >> output.txt;done?
streamofstars

2
Liên kết ParsingLs bắt buộc , cùng với một downvote (và bạn xứng đáng có nhiều hơn một downvote, bởi vì ls | greplà một antipotype xấu nghiêm trọng).
gniourf_gniourf

Có một upvote từ tôi vì nó cho phép thử nghiệm / thao tác tùy ý theo tên tệp trước khi xuất và nó nhanh chóng và dễ dàng và tốt cho thực hành. (Trong trường hợp của tôi, tôi muốn: for i in *; làm echo -e "\ n $ i: \ n"; mèo $ 1; thực hiện)
Nathan Chappell

Sẽ không ls *.txtthất bại nếu có quá nhiều tệp (Danh sách đối số lỗi quá dài)?
Rafael Almeida

6

cách thực dụng nhất với vỏ là lệnh mèo. những cách khác bao gồm,

awk '1' *.txt > all.txt
perl -ne 'print;' *.txt > all.txt

1
Đây phải là câu trả lời chính xác cho hầu hết các trường hợp. Nếu bất kỳ tệp văn bản nào không có dòng mới trống, sử dụng tất cả các catphương pháp trên sẽ nối dòng cuối cùng và dòng đầu tiên từ các tệp liền kề.
xe mô tô

6

Làm thế nào về phương pháp này?

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

Vì OP cho biết các tệp nằm trong cùng thư mục, bạn có thể cần thêm -maxdepth 1vào findlệnh.
codeforester

1
Hoạt động tốt với một số lượng lớn các tập tin, nơi mà phương pháp này trả lời được chấp nhận thất bại trong
amin

ah tôi ước tôi biết điều này cộng và chuyển hướng kép có nghĩa là gì ...
hello_earth

Đây phải là câu trả lời chính xác. Nó sẽ hoạt động đúng trong một kịch bản shell. Đây là một phương pháp tương tự nếu bạn muốn đầu ra được sắp xếp: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]

Ví dụ:

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

Điều đó sẽ lấy tất cả các tệp txt trong Thư mục C: \ và lưu nó trong Thư mục C: \ 1 theo tên của all.txt

Hoặc là

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

Ví dụ:

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

Điều đó sẽ lấy tất cả các tệp có trong thư mục và đặt ở đó Nội dung trong C: \ 1 \ all.txt


0

Bạn có thể làm như thế này: cat [directory_path]/**/*.[h,m] > test.txt

nếu bạn sử dụng {}để bao gồm phần mở rộng của các tệp bạn muốn tìm, có một vấn đề tuần tự.


0

Khi bạn gặp phải sự cố trong đó xử lý all.txt vào all.txt, Bạn có thể thử kiểm tra all.txt có tồn tại hay không, nếu có, hãy xóa

Như thế này:

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


cat *.txt > all.txt >lệnh ghi đè all.txt nếu nó tồn tại >>thêm dữ liệu vào tệp hiện có
Oleg Bondarenko

-4

tất cả điều đó thật khó chịu ....

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

công cụ dễ dàng.


6
Eeek! Đừng làm vậy. Dofind . -iname "*.txt" -maxdepth 1 -exec cat {} >> out.txt \;
Chinmay Kanchi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.