Làm cách nào để hợp nhất tất cả các tệp (văn bản) trong một thư mục thành một?


89

Tôi đã có 14 tệp tất cả là một phần của một văn bản. Tôi muốn hợp nhất chúng thành một. Làm thế nào để làm điều đó?

Câu trả lời:


168

Đây là về mặt kỹ thuật cat("concatenate") được cho là phải làm, mặc dù hầu hết mọi người chỉ sử dụng nó để xuất các tệp ra thiết bị xuất chuẩn. Nếu bạn cung cấp cho nó nhiều tên tệp, nó sẽ xuất tất cả chúng theo tuần tự, và sau đó bạn có thể chuyển hướng nó thành một tệp mới; trong trường hợp tất cả các tệp chỉ cần sử dụng *(hoặc /path/to/directory/*nếu bạn chưa có trong thư mục) và trình bao của bạn sẽ mở rộng nó sang tất cả các tên tệp

$ cat * > merged-file

15
Coi chừng rằng lệnh được trích dẫn của bạn có thể sẽ chỉ thực hiện những gì người đăng muốn nếu chúng được đánh số theo cách mà vỏ mở rộng *theo thứ tự "tự nhiên". Nếu bạn có "file1.txt ... file9.txt ... file14.txt" thì nó sẽ không hoạt động vì file1? .Txt sẽ sắp xếp giữa file1.txt và file2.txt. Bạn sẽ phải đổi tên chúng thành "file01.txt ... file09.txt ... file14.txt". Nói echo *nếu bạn không chắc chắn.
Warren Young

2
@Warren: điểm tốt (hoặc bạn có thể sử dụng zsh và đặt numeric_glob_sorttùy chọn của nó ).
Gilles

2
@ warren-young một bình luận cảnh báo chính xác, hữu ích. Nhưng trong trường hợp thực tế của tôi, thứ tự không có sự khác biệt (vì các tệp chỉ chứa các câu lệnh SQL đơn giản chèn các bản ghi dữ liệu không có phụ thuộc).
Ivan

2
Coi chừng, nếu số lượng tệp vượt quá một giới hạn nhất định, bạn có thể chạy trong các lỗi như - / bin / cat: Danh sách đối số quá dài
Nupur

1
@ ARA1307 Chỉ khi tệp đã tồn tại; nếu không thì toàn cầu sẽ được mở rộng trước khi shell mở tệp để ghi vào nó. Điểm tốt trong tình huống đó mặc dù
Michael Mrozek

25

Nếu các tệp của bạn không nằm trong cùng thư mục, bạn có thể sử dụng lệnh find trước khi ghép:

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

Rất hữu ích khi các tệp của bạn đã được đặt hàng và bạn muốn hợp nhất chúng để phân tích chúng.


Đáng chú ý hơn:

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

Điều này có thể hoặc không thể giữ trật tự tập tin.


1
Đây là cách để đi nếu bạn có nhiều tệp. Bạn tránh một lỗi "danh sách đối số quá dài".
Мати Тернер

2
Bạn cần -name "* .csv" thay vì -name * .csv - mà không có dấu ngoặc kép thì không thành công.
Peteris

Nhu cầu báo giá phụ thuộc vào phiên bản của lệnh find, đặc biệt là trong find và awk đó là một vấn đề khi bạn ở trên máy mac, phiên bản của cả hai chương trình đều hơi cũ. Cho đến nay, trên Ubuntu, fedora, debian và CentOS, nó hoạt động trơn tru mà không cần trích dẫn
3nrique0

Tôi hy vọng phiên bản không được trích dẫn sẽ hoạt động khi không có tệp nào trong thư mục hiện tại khớp với mẫu "*.csv", vì trình bao sau đó sẽ chuyển nghĩa đen *sang find.
RJHunter


9

Lệnh

$ cat * > merged-file

thực sự có tác dụng phụ không mong muốn bao gồm 'tập tin hợp nhất' trong phần ghép, tạo ra một tập tin bỏ chạy. Để hoàn thành vòng này, hãy ghi tệp đã hợp nhất vào một thư mục khác;

$ cat * > ../merged-file

hoặc sử dụng khớp mẫu sẽ bỏ qua tệp đã hợp nhất;

$ cat *.txt > merged-file

14
cat * > merged-filehoạt động tốt Globs được xử lý trước khi tập tin được tạo ra. Nếu merged-fileđã tồn tại, cat(ít nhất là của tôi) sẽ phát hiện ra rằng đó là tệp đầu ra và từ chối đọc nó. NẾU tệp đã tồn tại VÀ bạn có chuyển hướng sau này trong đường ống, thì rõ ràng nó không thể làm điều đó, vì vậy và sau đó bạn mới nhận được tệp chạy.
Kevin

catkhông có cách nào để phát hiện nếu tập tin là đầu ra. Sự chuyển hướng xảy ra trong vỏ; catchỉ in trên thiết bị xuất chuẩn.
bfontaine

8

Giống như những người khác ở đây nói ... Bạn có thể sử dụng cat

Hãy nói rằng bạn có:

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

Và bạn muốn chỉ file01đến file03fileAđể fileC:

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

Hoặc, sử dụng mở rộng cú đúp:

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

Hoặc, sử dụng mở rộng niềng răng fancier:

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

Hoặc bạn có thể sử dụng forvòng lặp:

for i in file0{1..3} file{A..C}; do cat ~/"$i"; done > merged-file

1
Lưu ý rằng chuỗi [01-03]sẽ không hoạt động như một mô hình toàn cầu.
Kusalananda

0

Bạn có thể chỉ định patterntệp của một tệp sau đó hợp nhất tất cả chúng như sau:

cat *pattern* >> mergedfile

0

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 ghi merge.txt (không phải 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à -n cho đầ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 với dấu ngoặc theo cách này:

sed -n w"merge.txt" {1..3}.txt
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.