วิธีต่อท้ายเนื้อหาของไฟล์หลาย ๆ ไฟล์เป็นไฟล์เดียว


174

ฉันต้องการคัดลอกเนื้อหาของห้าไฟล์ไปยังหนึ่งไฟล์ตามที่เป็นอยู่ ฉันลองทำโดยใช้ cp สำหรับแต่ละไฟล์ แต่นั่นเขียนทับเนื้อหาที่คัดลอกมาจากไฟล์ก่อนหน้า ฉันก็ลอง

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

และมันไม่ทำงาน

ฉันต้องการให้สคริปต์ของฉันเพิ่มบรรทัดใหม่ที่ท้ายไฟล์ข้อความแต่ละไฟล์

เช่น. ไฟล์ 1.txt, 2.txt, 3.txt ใส่เนื้อหาของ 1,2,3 ใน 0.txt

ฉันต้องทำอย่างไร ?


1
อาจเป็นไปได้ที่ซ้ำกันของการต่อไฟล์และแทรกบรรทัดใหม่ในระหว่างไฟล์
Nikos C.

อีกคำตอบที่นี่: stackoverflow.com/questions/2576693/…
Nikos C.

คำตอบ:


308

คุณต้องใช้catคำสั่ง (ย่อสำหรับเชื่อมต่อ) พร้อมกับการเปลี่ยนเส้นทางเชลล์ ( >) ในไฟล์เอาต์พุตของคุณ

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

8
>> ควรใช่มั้ย และทำไมถึงมีการขึ้นบรรทัดใหม่ต่อหน้าข้อความทั้งหมดในไฟล์ 0.txt ของฉัน
Steam

1
คุณต้องการที่จะรักษาเนื้อหาของ 0.txt หรือไม่?
sehe

13
@ blasto มันขึ้นอยู่กับ คุณจะใช้>>ในการผนวกหนึ่งไฟล์ไปยังอีกที่> เขียนทับไฟล์ที่ส่งออกกับสิ่งที่กำกับเป็นมัน ส่วนการขึ้นบรรทัดใหม่มีการขึ้นบรรทัดใหม่เป็นอักขระตัวแรกในไฟล์1.txtหรือไม่ คุณสามารถค้นหาข้อมูลโดยใช้และเห็นว่าตัวอักษรตัวแรกเป็นod -c \n
radical7

1
@ radical7 ขอบคุณ จริงๆแล้วไฟล์ของฉันเหมือน foo_1, foo_2, foo_3 ฉันพยายามแก้ไขรหัสของคุณในฐานะ - cat "$ filename _" {1,2,3} ". txt" แต่มันไม่ทำงาน
Steam

1
@ blasto คุณมุ่งหน้าไปในทิศทางที่ถูกต้องอย่างแน่นอน Bash ยอมรับรูปแบบ{...}การจับคู่ชื่อไฟล์อย่างแน่นอนดังนั้นราคาอาจทำให้สคริปต์ของคุณยุ่งเหยิงไปหน่อย? ฉันมักจะลองทำงานกับสิ่งต่าง ๆ เช่นนี้ใช้lsในเปลือก เมื่อฉันได้รับคำสั่งอย่างถูกต้องฉันเพิ่งตัดแปะมันลงในสคริปต์อย่างที่เป็นอยู่ คุณอาจพบว่า-xตัวเลือกที่มีประโยชน์ในสคริปต์ของคุณ - มันจะสะท้อนคำสั่งขยายในสคริปต์ก่อนที่จะดำเนินการ
radical7

97

ตัวเลือกอื่นสำหรับผู้ที่ยังคงสะดุดกับโพสต์นี้เหมือนที่ฉันทำคือการใช้find -exec:

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

ในกรณีของฉันฉันต้องการเป็นตัวเลือกที่มีประสิทธิภาพมากขึ้นที่จะมองผ่านไดเรกทอรีย่อยหลาย ๆ findดังนั้นผมจึงเลือกที่จะใช้งาน ทำลายมันลง:

find .

ดูในไดเรกทอรีการทำงานปัจจุบัน

-type f

สนใจเฉพาะไฟล์ไม่ใช่ไดเร็กตอรี่ ฯลฯ

-name '*.txt'

ลดผลการตั้งชื่อให้น้อยลง

-exec cat {} +

ดำเนินการคำสั่ง cat สำหรับแต่ละผลลัพธ์ "+" หมายถึงวางเพียง 1 อินสแตนซ์เท่านั้นcat(thx @gniourf_gniourf)

 >> output.file

ดังที่อธิบายไว้ในคำตอบอื่น ๆ ผนวกเนื้อหา cat-ed ต่อท้ายไฟล์เอาต์พุต


10
คำตอบนี้มีข้อบกพร่องมากมาย ขั้นแรก*.txtจะต้องใช้อักขระตัวแทน(มิฉะนั้นfindคำสั่งทั้งหมดตามที่เขียนจะไม่มีประโยชน์) ข้อบกพร่องอีกประการหนึ่งมาจากความเข้าใจผิดขั้นต้น: คำสั่งที่จะดำเนินการไม่ได้ แต่cat >> 0.txt {} cat {}อันที่จริงคำสั่งของคุณเทียบเท่ากับ{ find . -type f -name *.txt -exec cat '{}' \; ; } >> 0.txt(ฉันได้เพิ่มการจัดกลุ่มเพื่อที่คุณจะได้ตระหนักถึงสิ่งที่เกิดขึ้นจริง) ข้อบกพร่องอีกประการหนึ่งคือการที่findจะไปหาไฟล์0.txtและcatจะบ่นโดยบอกว่าแฟ้มใส่เป็นไฟล์ที่ส่งออก
gniourf_gniourf

ขอบคุณสำหรับการแก้ไข กรณีของฉันแตกต่างกันเล็กน้อยและฉันไม่เคยนึกถึง gotchas เหล่านั้นมาใช้กับกรณีนี้
mopo922

คุณควรวาง>> output.fileคำสั่งไว้ท้ายสุดเพื่อไม่ให้ใครก็ตาม (รวมถึงตัวคุณเอง) คิดว่าfindจะดำเนินการcat {} >> output.fileกับทุก ๆ ไฟล์ที่พบ
gniourf_gniourf

เริ่มที่จะดูดีจริงๆ! หนึ่งข้อเสนอแนะขั้นสุดท้าย: ใช้-exec cat {} +แทน-exec cat {} \;เพื่อให้มีเพียงอินสแตนซ์เดียวเท่านั้นที่catได้รับมาพร้อมกับอาร์กิวเมนต์หลายตัว ( +ระบุโดย POSIX )
gniourf_gniourf

3
คำตอบที่ดีและคำเตือน - ฉันแก้ไขของฉันเป็น: find . -type f -exec cat {} + >> outputfile.txtและไม่สามารถเข้าใจได้ว่าทำไมไฟล์ที่ส่งออกของฉันจะไม่หยุดการเจริญเติบโตในกิ๊กแม้ว่าไดเรกทอรีเป็นเพียง 50 เมกะไบต์ เป็นเพราะฉันยังคงผนวก outputfile.txt กับตัวเอง ดังนั้นให้แน่ใจว่าตั้งชื่อไฟล์นั้นถูกต้องหรือวางไว้ในไดเรกทอรีอื่นทั้งหมดเพื่อหลีกเลี่ยงปัญหานี้
Thisisstackoverflow

43

หากคุณมีเอาต์พุตบางประเภทให้ทำสิ่งนี้

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

1
โปรดจำไว้ว่าคุณกำลังสูญเสียความเป็นไปได้ที่จะรักษาความสงบเรียบร้อย สิ่งนี้อาจส่งผลกระทบต่อคุณหากคุณมีไฟล์ชื่อเช่น file_1,, file_2file_11เนื่องจากลำดับที่เป็นธรรมชาติของการเรียงลำดับไฟล์
emix

16

หากไฟล์ทั้งหมดของคุณอยู่ในไดเรกทอรีเดียวคุณสามารถทำได้

cat * > 0.txt

ไฟล์ 1.txt, 2.txt, .. จะเข้าสู่ 0.txt


ตอบโดย Eswar แล้ว โปรดจำไว้ว่าคุณกำลังสูญเสียความเป็นไปได้ที่จะรักษาความสงบเรียบร้อย สิ่งนี้อาจส่งผลกระทบต่อคุณหากคุณมีไฟล์ชื่อเช่น file_1,, file_2file_11เนื่องจากลำดับที่เป็นธรรมชาติของการเรียงลำดับไฟล์
emix

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

ฉันพบหน้านี้เพราะฉันต้องการเข้าร่วม 952 ไฟล์เข้าด้วยกันเป็นหนึ่งเดียว ฉันพบว่าสิ่งนี้ทำงานได้ดีขึ้นมากถ้าคุณมีไฟล์จำนวนมาก สิ่งนี้จะวนซ้ำสำหรับหมายเลขที่คุณต้องการและจัดให้แต่ละหมายเลขโดยใช้ >> เพื่อต่อท้าย 0.txt


คุณสามารถใช้วงเล็บปีกกาในการทุบตีเพื่อเขียน cat {1,2,3} .txt >> 0.txt
mcheema

9

หากไฟล์ทั้งหมดของคุณมีชื่อคล้ายกันคุณสามารถทำได้:

cat *.log >> output.log

5

ตัวเลือกอื่นคือsed:

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

หรือ...

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

หรือ...

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

หรือไม่มีการเปลี่ยนเส้นทาง ...

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

โปรดทราบว่าบรรทัดสุดท้ายเขียนด้วยmerge.txt(ไม่ใช่wmerge.txt!) คุณสามารถใช้w"merge.txt"เพื่อหลีกเลี่ยงความสับสนกับชื่อไฟล์และ-nสำหรับเอาต์พุตเงียบ

แน่นอนคุณยังสามารถย่อรายการไฟล์ด้วยไวด์การ์ด ตัวอย่างเช่นในกรณีของไฟล์ที่มีหมายเลขตามตัวอย่างด้านบนคุณสามารถระบุช่วงด้วยเครื่องหมายปีกกาด้วยวิธีนี้:

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

4

หากไฟล์ของคุณมีส่วนหัวและคุณต้องการลบออกในไฟล์เอาต์พุตคุณสามารถใช้:

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

3

หากไฟล์ต้นฉบับมีอักขระที่ไม่สามารถพิมพ์ได้ไฟล์เหล่านั้นจะหายไปเมื่อใช้คำสั่ง cat การใช้ 'cat -v' ไฟล์ที่ไม่สามารถพิมพ์ได้จะถูกแปลงเป็นสตริงอักขระที่มองเห็นได้ แต่ไฟล์เอาต์พุตจะยังไม่มีอักขระที่พิมพ์ได้จริงในไฟล์ต้นฉบับ ด้วยไฟล์จำนวนน้อยทางเลือกอื่นอาจเป็นการเปิดไฟล์แรกในโปรแกรมแก้ไข (เช่น vim) ที่จัดการอักขระที่ไม่พิมพ์ จากนั้นจึงจัดทำที่ด้านล่างของไฟล์และป้อน ": r second_file_name" ที่จะดึงในไฟล์ที่สองรวมถึงตัวละครที่ไม่ได้พิมพ์ สามารถทำเช่นเดียวกันสำหรับไฟล์เพิ่มเติม เมื่ออ่านไฟล์ทั้งหมดแล้วให้ป้อน ": w" ผลลัพธ์ที่ได้คือตอนนี้ไฟล์แรกจะมีสิ่งที่มันทำในตอนแรกรวมถึงเนื้อหาของไฟล์ที่อ่านมา


นี่เป็นสคริปต์ที่ไม่มากนัก
FKEinternet

1

หากคุณต้องการผนวกเนื้อหาของ 3 ไฟล์ไว้ในไฟล์เดียวคำสั่งต่อไปนี้จะเป็นตัวเลือกที่ดี:

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

มันจะรวมเนื้อหาของไฟล์ทั้งหมดลงใน file4 /dev/nullขว้างเอาท์พุทคอนโซล

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.