ฉันจะคัดลอกเนื้อหาของทุกไฟล์ในรายการไปยังไฟล์อื่นได้อย่างไร?


15

list_of_files.txtฉันมีรายชื่อของชื่อไฟล์ในไฟล์ที่เรียกว่า

all_compounds.sdfฉันต้องการที่จะคัดลอกเนื้อหาของแต่ละไฟล์ในรายการที่เป็นไฟล์อื่นที่เรียกว่า

ฉันจะทำสิ่งนี้จากบรรทัดคำสั่งได้อย่างไร

คำตอบ:


20

อย่าใช้การแทนที่คำสั่งง่ายๆเพื่อรับชื่อไฟล์ (ซึ่งอาจแตกได้ง่ายด้วยช่องว่างและอักขระพิเศษอื่น ๆ ) ใช้สิ่งที่ชอบxargs:

xargs -d '\n' -a list_of_files.txt cat > all_compounds.sdf

หรือwhile readวง:

while IFS= read -r file; do cat "$file"; done < list_of_files.txt > all_compounds.sdf

หากต้องการใช้การทดแทนคำสั่งอย่างปลอดภัยอย่างน้อยIFSต้องตั้งเป็นเพียงขึ้นบรรทัดใหม่และปิดการใช้งาน globbing (การขยายสัญลักษณ์แทน):

(set -f; IFS=$'\n'; cat $(cat list_of_files.txt) > all_compounds.sdf)

เครื่องหมายวงเล็บโดยรอบคือ()การเรียกใช้สิ่งนี้ใน subshell เพื่อให้เชลล์ปัจจุบันของคุณไม่ได้รับผลกระทบจากการเปลี่ยนแปลงเหล่านี้


14

วิธีที่รวดเร็วและสกปรก ...

cat $(cat list_of_files.txt) >> all_compounds.sdf

โปรดทราบ:วิธีนี้ใช้งานได้เฉพาะเมื่อชื่อไฟล์ในรายการของคุณมีพฤติกรรมที่ดีมาก - สิ่งต่าง ๆ จะผิดพลาดหากมีช่องว่างบรรทัดใหม่หรืออักขระใด ๆ ที่มีความหมายพิเศษกับเชลล์ - ใช้คำตอบนี้แทนผลลัพธ์ที่เชื่อถือได้)

หมายเหตุ

  • catcon cat enates ไฟล์ มันยังพิมพ์เนื้อหาของพวกเขา
  • การใช้การทดแทนคำสั่งcommand2 $(command1)คุณสามารถส่งผ่านผลลัพธ์ของcommand1( cat list...) ไปยังcommand2( cat) ซึ่งเชื่อมไฟล์เข้าด้วยกัน
  • จากนั้นใช้การเปลี่ยนเส้นทาง>>เพื่อส่งออกไปยังไฟล์แทนที่จะพิมพ์ไปยัง stdout หากคุณต้องการดูผลลัพธ์ให้ใช้teeแทน:

    cat $(cat list_of_files.txt) | tee -a all_compounds.sdf

(ฉันได้ใช้>>แทน>และteeใช้-aสวิตช์ในกรณีที่ไฟล์ของคุณมีอยู่แล้ว - ส่วนนี้จะต่อท้ายไฟล์แทนการเขียนทับหากมีอยู่แล้ว)


1
@Zanna อ้างถึงการแทนที่คำสั่งเพื่อหลีกเลี่ยงการแยกคำเช่น"$(cat list_of_files.txt)"
Sergiy Kolodyazhnyy

4
@Serg หากการแยกคำไม่เสร็จสิ้นcatจะทำให้รายการทั้งหมดเป็นหนึ่งอาร์กิวเมนต์
muru

@muru ตกลงเราจะจัดการกับชื่อไฟล์ที่มีช่องว่างได้อย่างไร?
Sergiy Kolodyazhnyy

1
@Serg ตั้งค่า IFS ตามนั้น - ดูย่อหน้าสุดท้ายของคำตอบของฉัน
muru

4

ในขณะที่ GNU awkเป็นยูทิลิตี้การประมวลผลข้อความ แต่ก็อนุญาตให้เรียกใช้คำสั่งเชลล์ภายนอกผ่านการsystem()โทร เราสามารถใช้สิ่งนั้นเพื่อประโยชน์ของเราเช่น:

$ awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt                                                        

ความคิดที่นี่เป็นเรื่องง่าย: เราอ่านบรรทัดไฟล์โดยสายและออกจากแต่ละบรรทัดที่เราสร้างการจัดรูปแบบสตริงซึ่งจะถูกส่งไปแล้วcat "File name.txt"system()

และนี่คือการดำเนินการ:

$ ls
file1.txt  file2.txt  file3 with space.txt  file_list.txt


$ awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt                                                        
Hi, I'm file2
Hi, I'm file1
Hi, I'm file3

ดังนั้นเราได้ทำส่วนใหญ่ของงานที่นั่น - เราพิมพ์ไฟล์ทั้งหมดในรายการ ส่วนที่เหลือนั้นง่าย: เปลี่ยนเส้นทางเอาต์พุตสุดท้ายไปยังไฟล์โดยมี>โอเปอเรเตอร์เป็นไฟล์สรุป

awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt > output.txt
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.