เหตุใดไฟล์ทั้งหมดจึงไม่ถูกบีบอัดและวิธีปรับปรุงโซลูชัน


8

ฉันมีโฟลเดอร์ที่มีไฟล์ประมาณ 20K ไฟล์จะถูกตั้งชื่อตามรูปแบบเช่นxy_{\d1,5}_{\d4}\.abc xy_12345_1234.abcฉันต้องการบีบอัด 10K แรกของพวกเขาโดยใช้คำสั่งนี้:

ls | sort -n -k1.4,1.9 | head -n10000 | xargs tar -czf xy_0_10000.tar.gz

อย่างไรก็ตามไฟล์ผลลัพธ์มีไฟล์ประมาณ 2K เท่านั้น

ls | sort -n -k1.4,1.9 | head -n10000 | wc -l อย่างไรก็ตามส่งคืน 10,000 ตามที่คาดไว้

ดูเหมือนว่าฉันจะเข้าใจผิดบางสิ่งพื้นฐานที่นี่ ...

ฉันใช้ zsh 5.0.2 บน Linux Mint 17.1, GNU tar 1.27.1

แก้ไข:

ฟอร์กแนะนำโดย @Archemar เสียงที่น่าเชื่อถือมากกับส้อมล่าสุดเขียนทับแฟ้มผล - ไฟล์ที่มี 'หาง' ของไฟล์ - 7773ที่จะ9999

ผลลัพธ์ของxargs --show-limit: Your environment variables take up 3973 bytes POSIX upper limit on argument length (this system): 2091131 POSIX smallest allowable upper limit on argument length (all systems): 4096 Maximum length of command we could actually use: 2087158 Size of command buffer we are actually using: 131072

แทนที่-cด้วย-rหรือ-uไม่ทำงานในกรณีของฉัน ข้อความแสดงข้อผิดพลาดคือtar: Cannot update compressed archives

ใช้ทั้งสอง-rและ-uไม่ถูกต้องและล้มเหลวด้วยtar: You may not specify more than one '-Acdtrux', '--delete' or '--test-label' option

แทนที่-cด้วย-aดูเหมือนจะไม่ถูกต้องเช่นกันและล้มเหลวด้วยเหมือนกันtar: You must specify one of the '-Acdtrux', '--delete' or '--test-label' optionsแต่ฉันไม่รู้จักปัญหาazfและAcdtruxดูเหมือนจะแยกกันกับฉัน

แก้ไข 2:

ลักษณะ -T เช่นวิธีที่ดีที่ผมได้นอกจากนี้ยังพบตัวอย่างที่นี่

อย่างไรก็ตามเมื่อฉันลอง

ls | sort -n -k1.4,1.9 | head -n10000 | tar -czf xy_0_10000.tar.gz -T - ฉันเข้าใจ tar: option requires an argument -- 'T'

บางทีชื่อไฟล์อาจไม่ถึงน้ำมันดินใช่ไหม แต่ดูเหมือนพวกเขาทำเพราะเมื่อฉันรัน

ls | sort -n -k1.4,1.9 | head -n10000 | tar --null -czf xy_0_10000.tar.gz -T - ฉันเข้าใจ tar: xy_0_.ab\nxy_1_...<the rest of filenames separated by literal \n>...998.ab Cannot stat: File name too long

เหตุใด tar จึงไม่เห็นชื่อไฟล์


และถ้าคุณลองแทน c ในคำสั่ง tar?
Olivier Dulac


1
ไฟล์ของ OP ไม่มีชื่อที่ยุ่งยาก
Archemar

@ 8bittree - เช่นเดียวกับคำแนะนำทั่วไปสำหรับเชลล์สคริปต์ที่แข็งแกร่งใช่ แต่สิ่งที่คุณแนะนำให้ใช้แทนการทำงานกับรายการไฟล์ที่มี oneliner แบบใช้ครั้งเดียวปกติ
kostja

1
@kostja ฉันจะใช้findซึ่งมี-print0ตัวเลือกให้ใช้ null เป็นตัวคั่นแทนการขึ้นบรรทัดใหม่ sortสามารถจัดการกับ-zธง headโชคไม่ดีที่ไม่ได้จัดการเข้าใจตัวคั่นไบต์โมฆะ แต่คำตอบนี้มีวิธีการแก้ปัญหาโดยใช้trการแลกเปลี่ยน\nและก่อนและหลัง\0 มีการอ่าน null คั่นชื่อไฟล์จาก headtar--null -T -stdin
8bittree

คำตอบ:


12

คุณถึงขีด จำกัด xargs แล้วหรือยัง

xargs --show-limit

ลอง :

  • สร้าง.tgzไฟล์จำลองtar czf xy_0_10000.tar.gz /hello/world
  • แทนที่-czfด้วย -Azf

เมื่อ xarg ถึงขีด จำกัด มันจะแยกคำสั่งดังนั้นคำสั่งที่คุณวิ่งสุดขั้วคือ

  tar czf xy_0_10000.tar.gz file1 file2 .... file666
  tar czf xy_0_10000.tar.gz file667 file668 ... file1203
  tar czf xy_0_10000.tar.gz file1024 ... file2000

เนื่องจาก tar แต่ละอันอยู่เหนือทับหน้าที่ผ่านมาคุณจะได้รับการtar cวิ่งครั้งสุดท้ายเท่านั้น

แก้ไข:

1) ตามman tarบน unbuntu -aและ -r ดูเหมือนว่าผนวกจะกระทำโดย (อย่างใดอย่างหนึ่ง) -A, --catenate, --concatenate

2) zip(ไม่gzip) สามารถใช้เพื่อเพิ่มไฟล์ได้บางทีตัวเลือก gzip จะทำการหลอกลวง (ใช้ | xargs zip -qr xy_0_0000.zipนี่จะส่งผลให้เป็นไฟล์ zip ไม่ใช่. tar.gz)

3) การใช้โซลูชันของ @ rsanchez
สิ่งสำคัญคือการเพิ่มตัวเลือกเพื่อ tar ในวิธีที่เหมาะสมลอง

ls | sort -n -k1.4,1.9 | head -n10000 |tar -czf xy_0_10000.tar.gz -T -

โดยที่ - -T -หมายถึงตัวเลือกการใช้งาน-Tและใช้-เป็นอาร์กิวเมนต์ให้กับ-T(คุณสามารถสร้างรายการไฟล์/tmp/foo.lstจากนั้นใช้-T /tmp/foo.lst)


สามารถ (= เพิ่ม) แทน c (= สร้าง / เขียนทับ) สามารถแก้ไขข้อ จำกัด นั้นได้หรือไม่?
Olivier Dulac

@OlivierDulac ( คำเตือน: นี่เป็นการคาดเดาอย่างแท้จริง ) มันอาจจะไม่สามารถแก้ไขได้เนื่องจาก tar ไม่สามารถสร้างไฟล์เปล่าได้ คุณสามารถบีบอัดโฟลเดอร์ว่างก่อนและใช้a (add)เพื่อเพิ่มไฟล์ลงในไฟล์ tar จากนั้นคุณสามารถเปิดน้ำมันดินและลบโฟลเดอร์ (ใช้ 7zip หรือบางอย่าง)
อิสมาเอลมิเกล

@ismaelmiguel: ฉันค่อนข้างแน่ใจว่ามันจะสร้างไฟล์อย่างมีความสุข ถ้าไม่ใช่เพียง:touch xy_0_10000.tar.gz && { _the full command here_ ; }
Olivier Dulac

1
@OlivierDulac นั่นจะเป็น.gzไฟล์ที่ไม่ถูกต้อง
Ismael Miguel

manpages ทั้งหมดที่ฉันเห็นจากmanpages.ubuntu.com/manpages/vivid/th/man1/tar.1.html (15.04) กลับสู่ความแม่นยำ (12.04) มีการ-rต่อท้าย แต่-aมีการบีบอัดอัตโนมัติที่ไม่เทียบเท่า และ-rzไม่ทำงาน: zipสามารถเพิ่มลงในไฟล์เก็บถาวรที่มีอยู่ได้เนื่องจากไดเรกทอรีไม่ได้ถูกบีบอัด แต่tarด้วยการบีบอัดจะบีบอัดข้อมูลเมตาดาต้าพร้อมกับข้อมูล คุณสามารถtar -rแบ่งข้อมูลลงในไฟล์บีบอัดที่ไม่บีบอัดแล้ว gzip ผลลัพธ์ หรือ ...
dave_thompson_085

12

xargsไม่จำเป็นต้องเป็น หากคุณโดยตรงให้ตัวเลือกที่จะอ่านชื่อไฟล์จากอินพุตมาตรฐานtar-T -

ตัวอย่างเช่น

... | tar -T - -czf xy_0_10000.tar.gz

ฉันดูเหมือนจะใช้ตัวเลือกไม่ถูกต้องไม่สามารถใช้งานได้กับไปป์ มีความพยายาม...| tar Tczf xy_..., ...| tar Tcz -f xy_... ...| tar -czf xy_... -T และอื่น ๆ อีกหลายพีชคณิต แต่กำลังได้รับเท่านั้นtar: You must specify one of the '-Acdtrux', '--delete' or '--test-label' options, tar: -f: Cannot stat: No such file or directoryถ้าใช้-fแยกต่างหากจากตัวเลือกอื่น ๆ tar: option requires an argument -- 'T'และ คุณช่วยเพิ่มตัวอย่างการใช้งานได้ไหม
kostja

เพิ่มตัวอย่าง @kostja แล้ว
rsanchez

ขอบคุณมาก rsanchez ไม่แน่ใจว่าทำไมตัวแปรที่มี-T -ในตอนท้ายของtarรายการตัวเลือกไม่ทำงาน แต่ตัวอย่างของคุณทำ น่าเสียดายที่คำถามของฉันมีอยู่สองส่วนจริง ๆ คือที่มาของข้อผิดพลาดและการปรับปรุงที่เป็นไปได้ ในขณะที่คุณเล่นบทหลัง Archemar เก่งในอดีตและเกือบจะมีสิทธิ์หลัง ฉันไม่แน่ใจว่าคำตอบใดของคุณที่ควรยอมรับเนื่องจากทั้งคู่มีประโยชน์ชัดเจน
kostja

1

ฉันต้องการที่จะเติมเต็มสองคำตอบอื่น ๆ ที่มีzshวิธีการแก้ปัญหาซึ่งไม่แยกวิเคราะห์คำสั่ง lsหรือต้องการxargs อย่างไรก็ตามฉันไม่แน่ใจว่าตอนนี้ถ้ามันทนทุกข์ทรมานจากข้อ จำกัด ของความยาวบรรทัดคำสั่ง

  1. $REPLYกำหนดฟังก์ชั่นซึ่งจะสร้างคีย์การเรียงลำดับที่คุณต้องการโดยการปรับเปลี่ยน

    sortkey() { REPLY=${REPLY[4,9]} }

    สิ่งนี้เทียบเท่ากับของคุณ sort -n -k1.4,1.9

  2. สร้างอาร์เรย์$filesด้วยชื่อไฟล์ที่เรียงลำดับด้วยฟังก์ชั่นด้านบน:

    files=(*(o+sortkey))

    สิ่งนี้เทียบเท่า ls | sort -n -k1.4,1.9

  3. ส่งคืนไฟล์ 10,000 ไฟล์แรกด้วย

    ${files[0,9999]}

    สิ่งนี้เทียบเท่า ls | sort -n -k1.4,1.9 | head -n10000

ดังนั้นทั้งหมดนี้ควรทำเคล็ดลับ:

sortkey() { REPLY=${REPLY[4,9]} }
files=(*(o+sortkey))
tar -czf xy_0_10000.tar.gz ${files[0,9999]}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.