Cách nối nội dung của nhiều tệp vào một tệp


173

Tôi muốn sao chép nội dung của năm tệp vào một tệp. Tôi đã thử làm nó bằng cách sử dụng cp cho mỗi tập tin. Nhưng điều đó ghi đè lên nội dung được sao chép từ tập tin trước đó. Tôi cũng đã thử

paste -d "\n" 1.txt 0.txt

và nó đã không hoạt động.

Tôi muốn tập lệnh của tôi thêm dòng mới vào cuối mỗi tệp văn bản.

ví dụ. Tập tin 1.txt, 2.txt, 3.txt. Đặt nội dung của 1,2,3 trong 0.txt

Tôi phải làm nó như thế nào ?



Một câu trả lời khác ở đây: stackoverflow.com/questions/2576693/ Mạnh
Nikos C.

Câu trả lời:


307

Bạn cần lệnh cat(viết tắt của concatenate), với shell redirection ( >) vào tệp đầu ra của bạn

cat 1.txt 2.txt 3.txt > 0.txt

8
nên >> phải không? và tại sao lại có một dòng mới trước tất cả văn bản trong tệp 0.txt của tôi?
Hấp

1
bạn có muốn giữ nội dung của 0.txt không?
sehe

13
@blasto nó phụ thuộc. Bạn sẽ sử dụng >>để nối một tập tin vào một tập tin khác, trong đó > ghi đè lên tập tin đầu ra với bất cứ điều gì được hướng vào nó. Đối với dòng mới, có một dòng mới là ký tự đầu tiên trong tệp 1.txtkhông? Bạn có thể tìm hiểu bằng cách sử dụng od -cvà xem nếu ký tự đầu tiên là a \n.
gốc7

1
@ triệt7 Cảm ơn. Thực tế, các tệp của tôi giống như foo_1, foo_2, foo_3. Tôi đã cố gắng sửa đổi mã của bạn thành - cat "$ filename _" {1,2,3} ". Txt", nhưng nó không hoạt động.
Hấp

1
@blasto Bạn chắc chắn đang đi đúng hướng. Bash chắc chắn chấp nhận hình thức {...}cho khớp tên tệp, vì vậy có lẽ các trích dẫn đã làm mọi thứ rối tung lên trong kịch bản của bạn? Tôi luôn cố gắng làm việc với những thứ như thế này bằng cách sử dụng lsvỏ. Khi tôi nhận được lệnh đúng, tôi chỉ cần cắt-dán nó vào một kịch bản. Bạn cũng có thể thấy -xtùy chọn hữu ích trong tập lệnh của mình - nó sẽ lặp lại các lệnh được mở rộng trong tập lệnh trước khi thực thi.
gốc7

97

Một lựa chọn khác, cho những bạn vẫn vấp phải bài đăng này như tôi đã làm, là sử dụng find -exec:

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

Trong trường hợp của tôi, tôi cần một tùy chọn mạnh mẽ hơn sẽ xem qua nhiều thư mục con nên tôi đã chọn sử dụng find. Phá vỡ nó:

find .

Nhìn vào thư mục làm việc hiện tại.

-type f

Chỉ quan tâm đến các tập tin, không phải thư mục, vv

-name '*.txt'

Giảm kết quả theo tên

-exec cat {} +

Thực hiện lệnh mèo cho mỗi kết quả. "+" chỉ có nghĩa là 1 trường hợp catđược sinh ra (thx @gniourf_gniourf)

 >> output.file

Như đã giải thích trong các câu trả lời khác, nối các nội dung cat-ed vào cuối tệp đầu ra.


10
Có rất nhiều sai sót trong câu trả lời này. Đầu tiên, ký tự đại diện *.txtphải được trích dẫn (nếu không, toàn bộ findlệnh, như được viết, là vô dụng). Một lỗ hổng khác xuất phát từ một quan niệm sai lầm thô thiển: lệnh được thực thi không phải cat >> 0.txt {} , nhưng cat {}. Lệnh của bạn trên thực tế tương đương với { find . -type f -name *.txt -exec cat '{}' \; ; } >> 0.txt(Tôi đã thêm nhóm để bạn nhận ra điều gì đang thực sự xảy ra). Một lỗ hổng khác findlà sẽ tìm tệp 0.txtcatsẽ khiếu nại bằng cách nói rằng tệp đầu vào là tệp đầu ra .
gniourf_gniourf

Cảm ơn đã sửa chữa. Trường hợp của tôi có một chút khác biệt và tôi đã không nghĩ về một số vấn đề được áp dụng cho trường hợp này.
mopo922

Bạn nên đặt >> output.fileở cuối lệnh của mình, để bạn không khiến bất kỳ ai (kể cả chính bạn) nghĩ rằng findsẽ thực thi cat {} >> output.filecho mọi tệp được tìm thấy.
gniourf_gniourf

Bắt đầu nhìn thực sự tốt! Một đề xuất cuối cùng: sử dụng -exec cat {} +thay vì -exec cat {} \;, để chỉ một trường hợp catđược sinh ra với một số đối số ( +được chỉ định bởi POSIX ).
gniourf_gniourf

3
Câu trả lời hay và lời cảnh báo - Tôi đã sửa đổi của tôi thành: find . -type f -exec cat {} + >> outputfile.txtvà không thể hiểu tại sao tệp đầu ra của tôi sẽ không ngừng phát triển trong hợp đồng biểu diễn mặc dù thư mục chỉ có 50 megs. Đó là bởi vì tôi đã tiếp tục nối thêm outputfile.txt vào chính nó! Vì vậy, chỉ cần đảm bảo đặt tên tệp đó một cách chính xác hoặc đặt nó trong thư mục khác hoàn toàn để tránh điều này.
Thisisstackoverflow

43

Nếu bạn có một loại đầu ra nhất định thì hãy làm một cái gì đó như thế này

cat /path/to/files/*.txt >> finalout.txt

1
Hãy nhớ rằng bạn đang mất khả năng duy trì trật tự hợp nhất mặc dù. Điều này có thể ảnh hưởng đến bạn nếu bạn có tên tệp của mình, vd. file_1,, tầm file_2, file_11vì thứ tự tự nhiên cách sắp xếp các tập tin.
emix

16

Nếu tất cả các tệp của bạn nằm trong một thư mục, bạn chỉ cần làm

cat * > 0.txt

Các tệp 1.txt, 2.txt, .. sẽ chuyển thành 0.txt


Đã được trả lời bởi Eswar. Hãy nhớ rằng bạn đang mất khả năng duy trì trật tự hợp nhất mặc dù. Điều này có thể ảnh hưởng đến bạn nếu bạn có tên tệp của mình, vd. file_1,, tầm file_2, file_11vì thứ tự tự nhiên cách sắp xếp các tập tin.
emix

10
for i in {1..3}; do cat "$i.txt" >> 0.txt; done

Tôi tìm thấy trang này vì tôi cần nối 952 tệp lại với nhau thành một. Tôi thấy điều này hoạt động tốt hơn nhiều nếu bạn có nhiều tập tin. Điều này sẽ thực hiện một vòng lặp cho nhiều số bạn cần và sử dụng từng số bằng cách sử dụng >> để nối vào cuối 0.txt.


bạn có thể sử dụng mở rộng cú đúp trong bash để viết cat {1,2,3} .txt >> 0.txt
mcheema

9

Nếu tất cả các tệp của bạn được đặt tên tương tự, bạn có thể chỉ cần làm:

cat *.log >> output.log

5

Một lựa chọn khác là sed:

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

Hoặc là...

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

Hoặc là...

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

Hoặc không có chuyển hướng ...

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

Lưu ý rằng dòng cuối cùng cũng viết merge.txt(không wmerge.txt!). Bạn có thể sử dụng w"merge.txt"để tránh nhầm lẫn với tên tệp và -ncho đầu ra im lặng.

Tất nhiên, bạn cũng có thể rút ngắn danh sách tập tin bằng ký tự đại diện. Ví dụ, trong trường hợp các tệp được đánh số như trong các ví dụ trên, bạn có thể chỉ định phạm vi có dấu ngoặc theo cách này:

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

4

nếu tệp của bạn chứa các tiêu đề và bạn muốn xóa chúng trong tệp đầu ra, bạn có thể sử dụng:

for f in `ls *.txt`; do sed '2,$!d' $f >> 0.out; done

3

Nếu tệp gốc chứa các ký tự không in được, chúng sẽ bị mất khi sử dụng lệnh cat. Sử dụng 'cat -v', các tệp không in được sẽ được chuyển đổi thành các chuỗi ký tự hiển thị, nhưng tệp đầu ra vẫn không chứa các ký tự không thể in thực tế trong tệp gốc. Với một số lượng nhỏ tệp, một giải pháp thay thế có thể là mở tệp đầu tiên trong trình chỉnh sửa (ví dụ vim) xử lý các ký tự không in. Sau đó di chuyển đến cuối tệp và nhập ": r second_file_name". Điều đó sẽ kéo trong tập tin thứ hai, bao gồm các ký tự không in. Điều tương tự có thể được thực hiện cho các tập tin bổ sung. Khi tất cả các tệp đã được đọc, nhập ": w". Kết quả cuối cùng là tệp đầu tiên bây giờ sẽ chứa những gì nó đã làm ban đầu, cộng với nội dung của các tệp đã được đọc.


Điều này không phải là rất kịch bản.
FKEiNET

1

Nếu bạn muốn chắp thêm nội dung của 3 tệp vào một tệp thì lệnh sau đây sẽ là một lựa chọn tốt:

cat file1 file2 file3 | tee -a file4 > /dev/null

Nó sẽ kết hợp nội dung của tất cả các tệp vào tệp4, ném đầu ra giao diện điều khiển sang /dev/null.

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.