การแยกไฟล์. gz ที่อยู่ในโฟลเดอร์


13

ฉันมีโฟลเดอร์ที่มีไฟล์. pdb.gz ประมาณ 320116 ฉันต้องการที่จะบีบอัดพวกเขาทั้งหมด ถ้าฉันใช้ gunzip * .gz มันทำให้ฉันมีข้อผิดพลาดคือรายการอาร์กิวเมนต์ยาวเกินไป โฟลเดอร์มีขนาดประมาณ 2GB โปรดให้คำแนะนำที่เหมาะสมแก่ฉัน


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

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

ฉันแนะนำให้คุณค้นหาคำถามที่คล้ายกันที่นั่น หากคุณไม่พบคนที่เหมาะกับความต้องการของคุณให้ถามคำถามใหม่ของคุณเอง
แดน

คำตอบ:


25
find . -name '*.pdb.gz' -exec gunzip {} +

-exec gunzip {} +จะจัดเตรียมgunzipชื่อไฟล์จำนวนมาก แต่ไม่มากเกินไปในบรรทัดคำสั่ง ซึ่งมีประสิทธิภาพมากกว่า-exec gunzip {} \;ที่จะเริ่มgunzipกระบวนการใหม่สำหรับแต่ละไฟล์


3
หนึ่งfindน้อยกว่าgunzip!
แดน

2
โปรดทราบว่า "+" เป็น GNUism และจะไม่ทำงานบนระบบที่ไม่ใช่ของ GNU เช่น * BSD
Reinstate Monica - M. Schröder

3
BSD รุ่นที่ใหม่กว่าfindอนุญาตให้ใช้เครื่องหมาย "+" ดูตัวอย่างเช่นหน้าคนสำหรับ BSD 10.1 ยังใช้กับ OS X (10.9 ขึ้นไปอย่างน้อยก็อาจเร็วกว่านี้) find
พลาสม่า

7

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

find . -type f -a -name \*.pdb.gz -print0 | xargs -0 gunzip

สิ่งนี้ไม่มีประสิทธิภาพเช่นเดียวกันกับ-execdir gunzip "{}" \;ที่ xargs จะเรียกใช้ gunzip แยกกันสำหรับแต่ละไฟล์หรือไม่ นั่นคือการอ่านหน้ามนุษย์ของฉัน
gogoud

5
ไม่xargsจะชื่อไฟล์มากเท่าที่จะพอดีกับgunzipบรรทัดคำสั่ง ลองมัน! echo a b c d e f | xargs echoเรียกใช้เพียงechoครั้งเดียวพร้อมอาร์กิวเมนต์ทั้งหมด 6 ข้อเพื่อให้คุณเห็นบรรทัดหนึ่งเอาต์พุต (คำสั่งที่ไม่มีประโยชน์พอที่จะดำเนินการได้ !!!!) ในขณะที่ถ้าคุณบังคับxargsให้จัดหาอาร์กิวเมนต์ได้มากถึง 3 ข้อต่อการเรียกใช้คำสั่งecho a b c d e f | xargs -n 3 echoนั้นคุณจะได้รับผลลัพธ์ 2 บรรทัด .
Celada

4
ข้อดีอีกอย่างของการใช้xargsคือด้วย-Pตัวเลือกคุณสามารถเรียกใช้หลายgunzipกระบวนการพร้อมกันซึ่ง (ขึ้นอยู่กับพารามิเตอร์ที่แน่นอนของระบบของคุณ) อาจทำงานได้เร็วขึ้น
psmears

ขอบคุณสำหรับตัวชี้ไปที่-P@psmears ตอนนี้ฉันก็ได้เรียนรู้บางสิ่งด้วย!
Celada

1

ฉันคิดว่ามันควรจะทำงานได้มันจะผ่านพา ธ / ชื่อของแต่ละไฟล์ไปยัง gunzip เพื่อทำการประมวลผล:

find /my/dir -name "*.pdb.gz" -execdir gunzip "{}" \;

1
ที่จะดำเนินการ gunzip หนึ่งไฟล์ต่อหนึ่งไฟล์ ดูคำตอบของ John1024สำหรับวิธีที่แตกต่างกันเล็กน้อยเพื่อหลีกเลี่ยงความไร้ประสิทธิภาพนั้น
Celada

@ Celada นี่เป็นเจตนา; ความกังวลของฉันคือการใช้ + อาจนำไปสู่ข้อผิดพลาดอีกครั้งเนื่องจากการโหลด gunzip มากเกินไป หากวิธีการของ John1024 ใช้ได้ผลดีกว่าในทางเทคนิค แต่ของฉันควรใช้งานได้ถ้าไม่ใช้
gogoud

1
findด้วย+และxargsเป็นผู้ออกแบบอย่างชัดแจ้งโดยมีปัญหาในใจ พวกเขามักจะให้ข้อโต้แย้งมากที่สุดเท่าที่จะทำได้ในขณะที่ไม่เกินขีด จำกัด ของระบบปฏิบัติการ เพราะโดยวิธีการที่มันเป็นข้อ จำกัด gunzipของระบบปฏิบัติการอะไรจะทำอย่างไรกับ
Celada

1
@Celada ok ขอบคุณสำหรับข้อมูลดังนั้นสันนิษฐานว่าด้วย '+' gunzip อาจถูกเรียกมากกว่าหนึ่งครั้ง แต่น้อยกว่า 320,000 ครั้ง?
gogoud

1
แก้ไข.
Celada

1

ลองด้วยวิธีนี้:

find . -name '*.gz' -exec gunzip {} \;

3
ที่จะดำเนินการgunzipหนึ่งครั้งต่อไฟล์ ดูคำตอบของ John1024สำหรับวิธีที่แตกต่างกันเล็กน้อยเพื่อหลีกเลี่ยงความไร้ประสิทธิภาพนั้น
Celada

อย่าลืม * ใน * .gz ...
user253751

1

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

find . -name "*.gz" | parallel -X gunzip {}

1
จะไม่ล้มเหลวเพราะรายการอาร์กิวเมนต์parallelยาวเกินไปหรือไม่
user253751

@immibis ใช่ฉันลืมปัญหาดั้งเดิมฉันจะอัปเดตโพสต์ของฉัน
Anthon

จะไม่ว่ายังคงล้มเหลวเนื่องจากรายการอาร์กิวเมนต์จะfindยาวเกินไป?
user253751

1
ใช่ แต่คุณกำลังส่งชื่อไฟล์ทั้งหมดในfindบรรทัดคำสั่งของ
user253751

ดูเหมือนว่าไม่ใช่วันที่ดีที่จะตอบคำถามฉันลืมอ้างถึงการโต้เถียง-name
Anthon

-1

ไม่จำเป็นต้องใช้findสำหรับสิ่งนี้เนื่องจากคุณไม่ได้พูดถึงโฟลเดอร์ย่อย สิ่งที่คุณต้องทำคือ:

for f in *.gz;do gunzip $f;done

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