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