ใช้คำสั่งกับไฟล์จำนวนมาก


19

ฉันมีโฟลเดอร์ที่มีไฟล์จำนวนมาก (xyz1, xyz2 ไปจนถึง xyz5025) และฉันต้องเรียกใช้สคริปต์ในทุก ๆ ไฟล์รับ xyz1.faa, xyz2.faa และอื่น ๆ

คำสั่งสำหรับไฟล์เดียวคือ:

./transeq xyz1 xyz1.faa -table 11

มีวิธีการทำเช่นนั้นโดยอัตโนมัติหรือไม่? อาจจะเป็นคำสั่งผสมที่ต้องทำ?

คำตอบ:


32
for file in xyz*
do
  ./transeq "$file" "${file}.faa" -table 11
done

นี่เป็นforลูปแบบง่ายที่จะวนซ้ำทุกไฟล์ที่ขึ้นต้นด้วยxyzในไดเรกทอรีปัจจุบันและเรียก./transeqโปรแกรมด้วยชื่อไฟล์เป็นอาร์กิวเมนต์แรกชื่อไฟล์ตามด้วย ".faa" เป็นอาร์กิวเมนต์ที่สองตามด้วย "-table 11" .


4
for file in xyz*; do ./transeq "$file" "${file}.faa" -table 11; doneหรือเป็นหนึ่งซับ: ฉันพิมพ์สิ่งนี้ตลอดเวลา และถ้าคุณต้องการตรวจสอบว่าชื่อไฟล์ ฯลฯ กำลังขยายแบบที่คุณต้องการเพียงแค่ใส่echoหลังจากdoครั้งแรกแล้วย้อนกลับไปในประวัติเชลล์ของคุณและลบมันในครั้งที่สอง
Dave Tweed

"$file".faaพิมพ์ได้ง่ายกว่าเล็กน้อยเนื่องจากเป็นส่วนหนึ่งของซับในแบบโต้ตอบและปลอดภัยเพราะ.faaไม่มีอักขระเชลล์ที่ต้องอ้างถึง
Peter Cordes

2
ตามที่ทราบถ้าคุณจบลงด้วยการวิ่งบางส่วนและต้องการที่จะรีสตาร์ทลูปxyz*glob จะรับไฟล์. faa เช่นกัน สำหรับ bash ให้รันshopt -s extglob( การอ้างอิง ) จากนั้นใช้for file in xyz!(*.faa) ...เพื่อแยกไฟล์. faa ไม่ให้ส่งผ่านลูป
Jeff Schaller

24

หากคุณติดตั้งGNU Parallelคุณสามารถทำได้ในลักษณะคู่ขนานดังนี้:

parallel ./transeq {} {}.faa -table 11 ::: xyz*

ถ้าโปรแกรมของคุณใช้ CPU มากควรเร่งความเร็วสักหน่อย


6

คุณสามารถทำสิ่งนี้ในbashบรรทัดคำสั่ง:

printf '%s\n' {1..5025} | xargs -l -I {} -t ./transeq xyz{} xyz{}.faa -table 11

เรากำลังสร้างจำนวนเต็มจาก 1 ถึง 5025 หนึ่ง / บรรทัดจากนั้นให้พวกเขาหนึ่งต่อหนึ่งถึง xargs ซึ่ง encapsulate จำนวนเต็มเข้าไป{}แล้วปลูกถ่ายมันลงในบรรทัดคำสั่ง. / transeq ในลักษณะที่เหมาะสม

หากคุณไม่ได้มีเครื่องมืออำนวยความสะดวกการขยายตัว{n..m}คุณสามารถเรียกใช้seqยูทิลิตี้เพื่อสร้างตัวเลขเหล่านั้น

หรือคุณสามารถเลียนแบบการสร้างตัวเลขผ่าน:

yes | sed -n =\;5025q | xargs ...

1
นั่นเป็นวิธีที่ซับซ้อนเกินไป for i in {1..5025}; do ./transeq "xyz$i" "xyz$i".faa -table 11; doneเป็นวิธีที่ง่ายต่อการคิดและพิมพ์ set -xหากคุณต้องการให้พิมพ์คำสั่งพวกเขาก่อนที่จะดำเนินการใช้
Peter Cordes

ใช่มันถูกต้อง แต่วิธีที่ OP กำหนดขึ้นมาสำหรับคำถามดูเหมือนว่าเฉพาะไฟล์ที่มีชื่อ xyz1 .. xyz5025 เท่านั้นที่เป็นที่สนใจ ดังนั้นฉันคิดว่าถ้าเราใช้กับ xyz * เราต้องมีวิธีที่จะปฏิเสธไฟล์ที่ไม่สอดคล้อง ... ด้วยเหตุนี้ เป็นการดีถ้า OP ต้องการไฟล์ทั้งหมดในไดเรกทอรีที่ประมวลผลแล้วทำไมถึงมีค่า 1 ถึง 5025 เพียงแค่บอกว่าฉันต้องการให้ไฟล์ทั้งหมดที่ประมวลผลในลักษณะที่กำหนดจะเพียงพอ

1
ดูที่ลูปที่ฉันเขียน มันใช้for i in {1..5025}เพื่อให้ได้ผลลัพธ์เช่นเดียวกับของคุณ คุณสามารถเขียนfor ((i=1 ; i<=5025 ; i++)); do ./transeq "xyz$i" "xyz$i".faa -table 11; doneด้วยการทุบตี แต่ฉันมักจะใช้{a..b}ช่วงไวยากรณ์เพราะพิมพ์ได้เร็วขึ้น
Peter Cordes

4

การใช้ find มีประโยชน์เมื่อไฟล์ของคุณกระจัดกระจายอยู่ในไดเรกทอรี

find -name "xyz*" -exec ./transeq {} {}.faa -table 11 \;

4

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

วิธีง่ายๆในการทำเช่นนี้คือผ่าน-Pพารามิเตอร์ของxargs- ตัวอย่างเช่นหากคุณมี 4 คอร์:

echo xyz{1..5025} | \
    xargs -n 1 -P 4 -I{} /path/to/transeq xyz{} xyz{}.faa -table 11

การ-n 1บอกxargsให้เลือกเพียงหนึ่งอาร์กิวเมนต์ออกจากรายการสำหรับการเรียกใช้แต่ละครั้ง(โดยค่าเริ่มต้นมันจะผ่านมากมาย)และการ-P 4บอกให้วางไข่ 4 กระบวนการในเวลาเดียวกัน - เมื่อมีคนตายคนใหม่จะเกิดใหม่

IMHO คุณไม่จำเป็นต้องติดตั้ง GNU ขนานสำหรับกรณีง่าย - xargsพอเพียง


0

คุณสามารถใช้ได้ xarg

ls | xargs -L 1 -d '\n' your-desired-command

-L 1 ทำให้เกิดการส่งผ่าน 1 รายการพร้อมกัน

-d '\n'ทำให้การส่งออกของlsถูกแยกขึ้นอยู่กับบรรทัดใหม่

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