วิธี "unextract" ไฟล์ซิปได้อย่างไร


52

ฉันคลายซิปไฟล์ลงในโฟลเดอร์ที่ไม่ว่างเปล่า ไฟล์ zip มีไฟล์จำนวนมากและลำดับชั้นลึกที่ผสานกับแผนผังที่มีอยู่ของไดเรกทอรีเป้าหมาย ฉันจะลบไฟล์และไดเรกทอรีที่สร้างโดยการแตกไฟล์โดยไม่ทำลายไฟล์และไดเรกทอรีที่มีอยู่แล้วได้อย่างไร แน่นอนฉันยังมีไฟล์ zip ที่ฉันรวมอยู่ด้วยดังนั้นข้อมูลจึงอยู่ที่นั่น


อืมขอบคุณที่ยอมรับ แต่มันเป็นความคิดของจินจินจริงๆ ฉันไม่รู้lqตัวเลือกสำหรับunzizpฉันเพิ่งเพิ่มเล่ห์กล * nix แบบคลาสสิกรอบคำตอบหลักของเขา
terdon

ไม่เป็นไรฉันไม่สนใจมากนัก ฉันได้เพิ่มการจัดการช่องว่างในเวอร์ชันอื่นของฉันเอง
jjlin

@terdon ใช่ ... ฉันสนับสนุนคำตอบของ jjlin ด้วย แต่ฉันสามารถตอบได้เพียงคำตอบเดียวเท่านั้น
mafp

สำหรับการอ้างอิงในอนาคตให้ทำหนึ่งในสิ่งต่อไปนี้ด้วยไฟล์เก็บถาวรที่ไม่คุ้นเคยของรูปแบบใด ๆ : 1) แยกไปยังไดเรกทอรีว่างเปล่าหรือ 2) เขียนรายการแรก (unzip -l) ก่อนที่จะแตกไฟล์เพื่อให้คุณสามารถดูว่า ไฟล์เก็บถาวรที่สร้างโดยไม่มีไดเรกทอรีระดับบนสุดพร้อมทุกสิ่งภายใต้รูปแบบที่ไม่ดี เมื่อทำกับ tar จริงๆแล้วพวกเขาเรียกว่าระเบิดทาร์ดังนั้นฉันคิดว่านี่อาจเรียกว่า zip bomb
Joe

@ Joe มันมีการใช้งาน แพ็คเกจ LaTeX สามารถมาในfoo.tds.zipรูปแบบ รหัสไปรษณีย์เหล่านี้รวมเข้ากับต้นไม้ TEXMF ซึ่งสะดวกมาก แต่ถ้าคุณต้องการลบแพคเกจดังกล่าวคุณต้องเผชิญกับปัญหาที่ฉันอธิบาย
mafp

คำตอบ:


28

คำตอบของjjlinคือหนทางที่จะไป ฉันแค่ต้องการเพิ่มตัวเลือกเล็กน้อยสำหรับไดเรกทอรี:

  • ลบไฟล์ที่แตกออกมาทั้งหมดไม่มีไดเรกทอรี :

    unzip -lqq file.zip | gawk -F"  " '{print $NF;}' |
      while IFS= read -r n; do rm "$n"; done
  • ลบไฟล์ที่คลายบีบอัดและไดเรกทอรีว่างเปล่าเท่านั้น

    unzip -lqq file.zip | gawk -F"  " '{print $NF;}' |
      while IFS= read -r n; do rm "$n"; done; rmdir *

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

  • ลบทุกอย่างที่แตกออก แต่ขอให้ยืนยันก่อนการลบแต่ละครั้ง:

    unzip -lqq file.zip | gawk -F"  " '{print $NF;}' |
      while IFS= read -r n; do rm -ri "$n"; done; rmdir *

    การ-iตั้งค่าสถานะจะทำให้rmการแจ้งเตือนก่อนการลบทุกครั้งคุณสามารถเลือกใช่หรือไม่

  • ลบทุกอย่างที่แยกไดเรกทอรีรวม:

    unzip -lqq file.zip | gawk -F"  " '{print $NF;}' |
      while IFS= read -r n; do rm -rf "$n"; done

การลบไดเรกทอรีว่างทำได้ง่ายๆด้วยfind: find * -depth -type d -exec rmdir {} +และไม่สนใจDirectory not emptyข้อความทั้งหมด อาจถูกกฎหมายในการย่อให้เหลือขนาดนี้find * -type d -deleteเป็น-deleteตัวเลือกที่เปิดอยู่-depthแต่ฉันไม่ได้ตรวจสอบว่า-deleteจะไม่ลบไดเรกทอรีที่ไม่ว่างเปล่า
Adrian Pronk

@AdrianPronk มันไม่ได้:find: cannot delete './foo': Directory not empty
terdon

28

คุณสามารถใช้unzip -lqq <filename.zip>เพื่อแสดงรายการเนื้อหาของไฟล์ zip; ซึ่งจะรวมถึงข้อมูลที่ไม่เกี่ยวข้องที่คุณจะต้องกรองออก นี่คือคำสั่งที่ใช้งานได้สำหรับฉัน:

unzip -lqq file.zip | awk '{print $4;}' | xargs rm -rf

awkคำสั่งสารสกัดจากเพียงแค่ชื่อของไฟล์และไดเรกทอรีที่ จากนั้นผลลัพธ์จะถูกส่งไปxargsยังเพื่อลบทุกอย่าง ฉันขอแนะนำให้ทำการรันคำสั่งแบบแห้ง (เช่นโดยเว้นxargs rm -rfส่วน) ก่อนเพื่อให้แน่ใจว่าผลลัพธ์นั้นถูกต้อง

คำสั่งดังกล่าวจะมีปัญหาในการจัดการกับเส้นทางที่มีช่องว่าง รุ่น (ซับซ้อนมากขึ้น) นี้ควรแก้ไขว่า:

unzip -lqq file.zip | awk '{$1=$2=$3=""; sub(/ */, "", $0); printf "%s%s", $0, "\0"}' | xargs -0 rm -rf

นี่ค่อนข้างใกล้เคียงกับสิ่งที่ฉันมีอยู่ในใจแล้ว แต่unzip -lqqยังแสดงรายการไดเรกทอรีที่อยู่ในรหัสไปรษณีย์ด้วย สำหรับตอนนี้ฉันจะให้ไดเรกทอรีทั้งหมดเพียงอย่างเดียว วิธีลบไดเรกทอรีที่ว่างเปล่าทั้งหมดในทรีอาจเป็นคำถามที่ตามมา
mafp

@mafp นั่นเป็นจุดที่ดีเกี่ยวกับไดเรกทอรี คุณสามารถเพิ่มgrep -v '/$'ลงในไพพ์ไลน์เพื่อข้ามการลบไดเรกทอรี (ซึ่งทั้งหมดมีเครื่องหมายสแลชต่อท้าย, AFAICT)
jjlin

@terdon จริงฉันคิดว่าปัญหาเริ่มต้นที่การawkพิมพ์เพียง $ 4 จะไม่พิมพ์เส้นทางแบบเต็ม
jjlin

ฉันไม่คิดว่าคุณควรใช้-rตัวเลือกของ rm: ดูเหมือนว่าจะถามปัญหาโดยเฉพาะเมื่อรวมกับ-fตัวเลือก ฉันจะไม่ใช้-fตัวเลือกเลยในสถานการณ์นี้
Adrian Pronk

1
@jjlin: grep -v '/$'จะละเว้นเฉพาะรายการไดเรกทอรีในไฟล์ ZIP พวกเขาจะยังคงรวมรายการที่เป็นไฟล์ธรรมดาในไฟล์ ZIP แต่เป็นไดเรกทอรีที่มีอยู่แล้วในโฟลเดอร์เป้าหมาย ด้วยเหตุนี้จึงเป็นการดีที่จะละเว้น-r
Adrian Pronk

11

เมื่อใช้สวิตช์การ-Z1คลายซิปจะแสดงรายการไฟล์หนึ่งไฟล์ต่อบรรทัดอย่างแน่นอน

ด้วยวิธีนี้คุณสามารถใช้

unzip -Z1 | xargs -I {} rm '{}'

เพื่อลบไฟล์ทั้งหมดที่ดึงมาจากไฟล์ซิป

คำสั่ง

unzip -Z1 | xargs -I {} rm -rf '{}'

จะลบไดเรกทอรีเช่นกัน แต่คุณต้องระวัง หากมีไดเร็กทอรีอยู่แล้วก่อนที่จะแตกไฟล์ zip ไฟล์ที่มีอยู่แล้วทั้งหมดในไดเร็กทอรีเหล่านั้นจะถูกลบเช่นกัน


หากคุณกำลังจะแตกไฟล์ zip ใหม่อีกครั้งมีวิธีอื่นที่รับประกันว่าจะจัดการกับชื่อไฟล์แปลก ๆ

ก่อนอื่นให้แตกไฟล์ zip ที่คุณตั้งใจจะแตกไฟล์:

unzip file.zip -d elsewhere

ตอนนี้เปลี่ยนเป็นไดเร็กทอรีที่คุณแตกไฟล์โดยไม่ได้ตั้งใจและรันคำสั่งต่อไปนี้:

find elsewhere -type f -printf "%P\0" | xargs -0 -I {} rm '{}'
  • -type f ค้นหาไฟล์เท่านั้น (ไม่มีไดเรกทอรี)

  • %P\0เป็นเส้นทางสัมพัทธ์ (ไม่รวมelsewhere/) ตามด้วยอักขระ null

  • -0ทำให้ xargs คั่นบรรทัดด้วยอักขระ null สิ่งนี้น่าเชื่อถือมากขึ้นเนื่องจากในทางทฤษฎีแล้วชื่อไฟล์สามารถมีอักขระขึ้นบรรทัดใหม่ได้


เพื่อจัดการกับไดเร็กทอรีที่เหลือคุณสามารถเรียกใช้งานคำสั่ง:

find -type d -exec rmdir -p {} \; 2> /dev/null
  • -type d ค้นหาเฉพาะไดเรกทอรี

  • -exec rmdir -p {} \;ดำเนินการrmdir -p {}สำหรับทุกไดเรกทอรีที่พบ

    {}เป็นไดเร็กทอรีที่ถูกค้นพบและ-pสวิตช์ทำให้ rmdir ลบไดเร็กทอรีพาเรนต์ว่างออกเช่นกัน

  • 2> /dev/null ไม่แสดงข้อความแสดงข้อผิดพลาดที่จะเกิดขึ้นจากการพยายามลบไดเรกทอรีที่ไม่ว่างเปล่าหรือลบไปก่อนหน้านี้


หน้าคนที่เกี่ยวข้อง:


+1 ที่ทำให้ฉันอ่านzipinfoหน้าคน
terdon

ดีที่ทำให้ง่ายขึ้นเล็กน้อย :)
jjlin

2

นี่เป็นทางออกที่ง่ายกว่าและปลอดภัยกว่า (ฉันคิดว่า)

zip -m getmeoutofhere.zip `unzip -lqq myoriginalzipfile.zip`
rm getmeoutofhere.zip

สิ่งนี้กำลังทำอะไร: คำสั่ง unquip คำสั่ง backquoted จะสร้างรายการสิ่งที่อยู่ในไฟล์ต้นฉบับของคุณ

ซิป -m จะใช้รายการที่จะเพิ่มเพิ่มว่าแต่ละ getmeoutofhere.zip และลบออกจากไดเรกทอรีเดิม (ดังนั้นในทางทฤษฎีมันควรจะเป็น indential เพื่อ myoriginalfile.zip

ข้อเสียคือการunzip -lqqจะสร้างข้อความพิเศษวันที่เวลาขนาดไฟล์เป็นต้นซึ่งจะทำให้ zip -m สร้างข้อความแสดงข้อผิดพลาด แต่สิ่งนี้ไม่ควรมีผลกระทบใด ๆ ชื่อ).

โปรดทราบว่าการทำเช่นนี้จะไม่ลบไดเรกทอรีใด ๆ ที่สร้างขึ้นในระหว่างการคลายซิปดั้งเดิม


วิธีการที่น่าสนใจจะสำรวจเพิ่มเติม
mafp

1

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

นี่เป็นสถานการณ์ที่เรียบง่าย

สมมติว่าไม่มีไฟล์ใดที่มีอยู่ในไดเรกทอรีปัจจุบันที่ถูกแตะอย่างน้อย 24 ชั่วโมง สิ่งใดก็ตามที่ได้รับการแก้ไขใน 24 ชั่วโมงที่ผ่านมาดังนั้นขยะจาก zipfile

$ find . -mtime -1 -print0 | xargs -0 rm

นี่จะค้นหาบางไดเร็กทอรีเช่นกัน แต่rmจะทิ้งไว้คนเดียว พวกเขาสามารถจัดการกับในรอบที่สอง:

$ find . -mtime 1 -type d -print 0 | xargs -0 rmdir

ไดเร็กทอรีใด ๆ ที่ถูกแก้ไขเมื่อเร็ว ๆ นี้ได้รับการแก้ไขโดย zip หากrmdirลบไฟล์ออกสำเร็จแสดงว่าไม่มีข้อมูล ไดเรกทอรีว่างที่ถูกสัมผัสโดย zip อาจถูกสร้างขึ้นโดยมัน: ie มาจากไฟล์เก็บถาวร เราไม่สามารถแน่ใจได้ 100% เป็นไปได้ว่างาน unzip ทำให้บางไฟล์ลงในไดเรกทอรีที่มีอยู่ซึ่งว่างเปล่า

หากfind24 ชั่วโมงของเมล็ดละเอียดไม่ดีพอสำหรับงานเนื่องจากไฟล์ในแผนผังถูกแก้ไขเร็ว ๆ นี้จากนั้นฉันจะพิจารณาบางสิ่งง่ายๆ: สมมติว่างาน unzip ไม่ได้ใส่อะไรลงในไดเรกทอรีย่อยที่มีอยู่ กล่าวคือทุกสิ่งที่ unzipped นั้นอาจเป็นไฟล์ที่ระดับบนสุดหรือไดเรกทอรีย่อยใหม่ซึ่งไม่เคยมีมาก่อนซึ่งประกอบด้วยเนื้อหาใด ๆ จาก zip แล้ว:

# list directory in descending order of modification time
$ ls -1t > filelist  # descending order of modification time

ตอนนี้เราเปิดfilelistในโปรแกรมแก้ไขข้อความและกำหนดรายการแรกในรายการที่ไม่ได้มาจาก zip เราลบรายการนั้นและทุกอย่างอื่นหลังจากนั้น สิ่งที่เหลืออยู่คือไฟล์และไดเรกทอรีที่มาจากรหัสไปรษณีย์ ก่อนอื่นเราจะตรวจสอบปัญหาเช่นการเว้นวรรคในชื่อและการปรากฏของคำพูดที่ต้องหลบหนี จากนั้นเราสามารถเพิ่มเครื่องหมายคำพูดรอบ ๆ ทุกสิ่งหากจำเป็น: สิ่งต่อไปนี้จะถือว่าคุณใช้ Vim:

:%s/.*/"&"/

จากนั้นเข้าร่วมทั้งหมดเป็นเส้นใหญ่:

:%j

ตอนนี้ใส่rm -rfข้างหน้ามัน:

Irm - rf<ESC>

รันบรรทัดภายใต้เคอร์เซอร์เป็นคำสั่งเชลล์:

!!sh<Enter>

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

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

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