list_of_files.txt
ฉันมีรายชื่อของชื่อไฟล์ในไฟล์ที่เรียกว่า
all_compounds.sdf
ฉันต้องการที่จะคัดลอกเนื้อหาของแต่ละไฟล์ในรายการที่เป็นไฟล์อื่นที่เรียกว่า
ฉันจะทำสิ่งนี้จากบรรทัดคำสั่งได้อย่างไร
list_of_files.txt
ฉันมีรายชื่อของชื่อไฟล์ในไฟล์ที่เรียกว่า
all_compounds.sdf
ฉันต้องการที่จะคัดลอกเนื้อหาของแต่ละไฟล์ในรายการที่เป็นไฟล์อื่นที่เรียกว่า
ฉันจะทำสิ่งนี้จากบรรทัดคำสั่งได้อย่างไร
คำตอบ:
อย่าใช้การแทนที่คำสั่งง่ายๆเพื่อรับชื่อไฟล์ (ซึ่งอาจแตกได้ง่ายด้วยช่องว่างและอักขระพิเศษอื่น ๆ ) ใช้สิ่งที่ชอบ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 เพื่อให้เชลล์ปัจจุบันของคุณไม่ได้รับผลกระทบจากการเปลี่ยนแปลงเหล่านี้
วิธีที่รวดเร็วและสกปรก ...
cat $(cat list_of_files.txt) >> all_compounds.sdf
โปรดทราบ:วิธีนี้ใช้งานได้เฉพาะเมื่อชื่อไฟล์ในรายการของคุณมีพฤติกรรมที่ดีมาก - สิ่งต่าง ๆ จะผิดพลาดหากมีช่องว่างบรรทัดใหม่หรืออักขระใด ๆ ที่มีความหมายพิเศษกับเชลล์ - ใช้คำตอบนี้แทนผลลัพธ์ที่เชื่อถือได้)
cat
con cat enates ไฟล์ มันยังพิมพ์เนื้อหาของพวกเขาcommand2 $(command1)
คุณสามารถส่งผ่านผลลัพธ์ของcommand1
( cat list...
) ไปยังcommand2
( cat
) ซึ่งเชื่อมไฟล์เข้าด้วยกันจากนั้นใช้การเปลี่ยนเส้นทาง>>
เพื่อส่งออกไปยังไฟล์แทนที่จะพิมพ์ไปยัง stdout หากคุณต้องการดูผลลัพธ์ให้ใช้tee
แทน:
cat $(cat list_of_files.txt) | tee -a all_compounds.sdf
(ฉันได้ใช้>>
แทน>
และtee
ใช้-a
สวิตช์ในกรณีที่ไฟล์ของคุณมีอยู่แล้ว - ส่วนนี้จะต่อท้ายไฟล์แทนการเขียนทับหากมีอยู่แล้ว)
cat
จะทำให้รายการทั้งหมดเป็นหนึ่งอาร์กิวเมนต์
ในขณะที่ 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
"$(cat list_of_files.txt)"