Nối các tệp và chèn dòng mới vào giữa các tệp


127

Tôi có nhiều tệp mà tôi muốn ghép nối cat. Hãy cùng nói nào

File1.txt 
foo

File2.txt
bar

File3.txt
qux

Tôi muốn nối để tệp cuối cùng trông giống như sau:

foo

bar

qux

Thay vì điều này với thông thường cat File*.txt > finalfile.txt

foo
bar 
qux

Cách thích hợp để làm điều đó là gì?


Câu trả lời:


121

Bạn có thể làm:

for f in *.txt; do (cat "${f}"; echo) >> finalfile.txt; done

Đảm bảo rằng tệp finalfile.txtkhông tồn tại trước khi bạn chạy lệnh trên.

Nếu bạn được phép sử dụng, awkbạn có thể làm:

awk 'FNR==1{print ""}1' *.txt > finalfile.txt

10
AWK '{print $0}' *.txt
timger

7
Điều này có một lỗ hổng rõ ràng là sẽ có các dòng trống ở cuối (từ phương án đầu tiên) hoặc ở đầu (phương án thứ hai). Tuy nhiên, bạn có thể dễ dàng bảo vệ chống lại điều này với awk 'FNR==1 && NR > 1 ...'.
tripleee

5
Nếu bạn đặt >finalfile.txtsau, donebạn có thể ghi đè thay vì nối thêm, điều này sẽ loại bỏ yêu cầu đảm bảo tệp bị thiếu hoặc trống trước vòng lặp.
tripleee

53

Nếu bạn có đủ ít tệp mà bạn có thể liệt kê từng tệp, thì bạn có thể sử dụng thay thế quy trình trong Bash, chèn một dòng mới giữa mỗi cặp tệp:

cat File1.txt <(echo) File2.txt <(echo) File3.txt > finalfile.txt

1
Xinh đẹp! Cảm ơn.
Bob Kocisko

Điều này hoạt động hiệu quả đối với tôi đối với chứng chỉ Letsencrypt của tôi để tạo tệp .pem.
leeman24

35

Nếu là tôi làm điều đó, tôi sẽ sử dụng sed:

sed -e '$s/$/\n/' -s *.txt > finalfile.txt

Trong mẫu sed này, $ có hai ý nghĩa, thứ nhất là nó chỉ khớp với số dòng cuối cùng (như một dải các dòng để áp dụng một mẫu) và thứ hai, nó khớp với cuối dòng trong mẫu thay thế.

Nếu phiên bản sed của bạn không có -s(xử lý các tệp đầu vào riêng biệt), bạn có thể thực hiện tất cả như một vòng lặp:

for f in *.txt ; do sed -e '$s/$/\n/' $f ; done > finalfile.txt

3
Hoặc trong GNU sed:sed -s '$G' *.txt > finalfile.txt
Ruud Helderman

Chỉ một luồng! đây phải là câu trả lời được chấp nhận!
Yassine ElBadaoui 23/02/18

các bạn hãy cẩn thận, tôi vừa gặp sự cố PC của mình vì tôi đã sử dụng findthay *.txtcho tệp, có nghĩa là tệp đã được nối vào chính nó!
Xerus

11

Bạn có thể làm điều đó bằng cách sử dụng xargsnếu bạn thích, nhưng ý tưởng chính vẫn giống nhau:

find *.txt | xargs -I{} sh -c "cat {}; echo ''" > finalfile.txt

1
Cảm ơn. Tôi thấy xargsdễ sử dụng hơn nhiều so với các vòng lặp trong bash.
RawwrBag

9

Điều này hoạt động trong Bash:

for f in *.txt; do cat $f; echo; done

Ngược lại với câu trả lời bằng >>(append), đầu ra của lệnh này có thể được đưa vào các chương trình khác.

Ví dụ:

  • for f in File*.txt; do cat $f; echo; done > finalfile.txt
  • (for ... done) > finalfile.txt (parens là tùy chọn)
  • for ... done | less (đường ống vào ít hơn)
  • for ... done | head -n -1 (điều này loại bỏ dòng trống ở cuối)

7

Đó là cách tôi vừa làm trên OsX 10.10.3

for f in *.txt; do (cat $f; echo '') >> fullData.txt; done

vì lệnh 'echo' đơn giản không có tham số nên không có dòng mới nào được chèn vào.


Điều này đặt chuỗi ở cuối tệp; làm cách nào để chèn nó vào giữa mỗi tệp?
onassar

3

Trong python, điều này nối với các dòng trống giữa các tệp ( ,ngăn chặn việc thêm một dòng trống ở cuối):

print '\n'.join(open(f).read() for f in filenames),

Đây là một lớp lót python xấu xí có thể được gọi từ shell và in kết quả ra một tệp:

python -c "from sys import argv; print '\n'.join(open(f).read() for f in argv[1:])," File*.txt > finalfile.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.