แตกไฟล์ zip ที่ซ้อนกัน


15

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


คุณหมายถึงอะไรโดยแยกสิ่งที่ไม่ใช่ไฟล์ zip คุณต้องการคัดลอกไปยังที่อื่นหรือไม่
phunehehe

ฉันไม่พบความต้องการของคุณชัดเจน ฉันพบShawn J. Goffและการตีความของฉันเกี่ยวกับโอกาสที่เท่าเทียมกัน คุณช่วยอธิบายได้ไหม
Gilles 'หยุดความชั่วร้าย'

@Gilles: ขออภัยใช่มันค่อนข้างชัดเจน ฉันเปลี่ยนมันเล็กน้อยหวังว่ามันชัดเจนขึ้นแล้ว
oadams

ฉันจะโพสต์คำตอบ แต่ฉันเชื่อว่ามันควรจะเป็นความคิดเห็นที่: จดหมายเหตุที่ซ้อนกันเพิ่มพื้นที่ที่คุณต้องการ! คุณอาจหมายถึงรูปแบบไฟล์ซิปไม่ใช่แค่ gzip ไฟล์ซิปทุกไฟล์ถูกบีบอัดแล้วบีบอัดอีกครั้งเพียงสร้างโอเวอร์เฮดมากขึ้นและเพิ่มพื้นที่ที่ต้องการอย่างมีประสิทธิภาพ
polemon

ใช่ฉันไม่ได้ทำ: พี น่าเสียดายที่ฉันต้องเผชิญกับวิธีที่แปลกประหลาดในการเผยแพร่ไฟล์
oadams

คำตอบ:


13

สิ่งนี้จะแยกไฟล์ zip ทั้งหมดลงในไดเรกทอรีปัจจุบันยกเว้นไฟล์ zip ที่อยู่ในนั้น

find . -type f -name '*.zip' -exec unzip -- '{}' -x '*.zip' \;

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

หากคุณต้องการไฟล์ทั้งหมดอย่างเคร่งครัดในไดเรกทอรีปัจจุบันคุณสามารถเรียกใช้

find . -type f -mindepth 2 -exec mv -- '{}' . \;

หมายเหตุ: ไฟล์นี้จะอุดตันหากมีสองไฟล์ที่มีชื่อเหมือนกันในไดเร็กทอรีที่ต่างกัน

หากคุณต้องการแตกไฟล์ zip และซิปภายในซ้ำทั้งหมดไฟล์ zip ต่อไปนี้จะแยกไฟล์ทั้งหมดในไดเรกทอรีปัจจุบันและซิปทั้งหมดที่อยู่ในไฟล์นั้นไปยังไดเรกทอรีปัจจุบัน

while [ "`find . -type f -name '*.zip' | wc -l`" -gt 0 ]
do
    find . -type f -name "*.zip" -exec unzip -- '{}' \; -exec rm -- '{}' \;
done

ในขณะที่การวนซ้ำช่วยฉันได้มากในการแข่งขันแฮ็คอย่างมีจริยธรรมซึ่งพวกเขาได้เตรียมไฟล์ซิปที่ซ้อนกันซึ่งมีระดับ 31337 ลึกขอบคุณ!
peedee

2
คุณอาจชอบตัวแปรนี้ที่ฉันใช้เพื่อแยกเนื้อหาซ้ำ ๆ จากหูที่ซ้อนกัน, สงคราม, ไฟล์ jar: gist.github.com/tyrcho/479c18795d997c201e53 ความแตกต่างที่สำคัญคือมันสร้างโฟลเดอร์ซ้อนสำหรับแต่ละไฟล์เก็บถาวร while [ "หา -type f -name '*.? ar' | wc -l" -gt 0 ]; do find -type f -name "*.?ar" -exec mkdir -p '{}.dir' \; -exec unzip -d '{}.dir' -- '../{}' \; -exec rm -- '{}' \;; done
Michel Daviot

4

เท่าที่ฉันเข้าใจคุณมีไฟล์เก็บถาวร zip ที่ตัวเองมีไฟล์เก็บถาวร zip และคุณต้องการคลายซิปรหัสไปรษณีย์ที่ซ้อนกันทุกครั้งที่มีการแตกไฟล์

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

shopt -s globstar nullglob
while set -- **/*.zip; [ $# -ge 1 ] do
  for z; do
    ( cd -- "$(dirname "$z")" &&
      z=${z##*/} &&
      unzip -- "$z" &&
      rm -- "$z"
    )
  done
done

สคริปต์ยังจะทำงานใน zsh ถ้าคุณเปลี่ยนสอดคล้องกับshoptsetopt nullglob

นี่คือการพกพาที่เทียบเท่า เงื่อนไขการเลิกจ้างมีความซับซ้อนเล็กน้อยเนื่องจากfindไม่ส่งคืนสถานะโดยธรรมชาติเพื่อระบุว่าพบไฟล์ใด ๆ หรือไม่ คำเตือน: ดังกล่าวข้างต้น

while [ -n "$(find . -type f -name '*.zip' -exec sh -c '
    cd "${z%/*}" &&
    z=${z##*/} &&
    unzip -- "$z" 1>&2 &&
    rm -- "$z" &&
    echo 1
')" ]; do :; done

1

unzipไม่ได้ทำเช่นนี้เพราะวิธี UNIX คือการทำสิ่งหนึ่งและทำได้ดีไม่จัดการกับกรณีพิเศษที่บ้าคลั่งในเครื่องมือทุกอย่าง ดังนั้นคุณต้องใช้เชลล์ (ซึ่งจะทำหน้าที่ของ "การผูกสิ่งต่าง ๆ เข้าด้วยกัน" ได้ดี) สิ่งนี้ทำให้เป็นคำถามการเขียนโปรแกรมและเนื่องจากคำถามการเขียนโปรแกรมที่เป็นไปได้ทั้งหมดได้รับการตอบกลับใน StackOverflow ที่นี่: คุณจะคลายการบีบอัดไฟล์เก็บถาวรในไดเรกทอรีและไดเรกทอรีย่อยจากบรรทัดคำสั่ง Unix ได้อย่างไร


1
ฉันจะไม่เรียก "การใช้เชลล์" คำถามการเขียนโปรแกรมและ "เชลล์สคริปต์" แสดงอยู่ในคำถามที่พบบ่อยในหัวข้อ
Michael Mrozek

ฉันไม่ได้หมายความว่ามันเป็นหัวข้อที่นี่เลยฉันแค่ต้องการพิสูจน์ว่าทำไมมันถึงอยู่ในหัวข้อที่ StackOverflow
Thomas Themel

1

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

#!/usr/bin/perl -w

# This script unzips all .zip files it finds in the current directory
# and all subdirectories.  Contents are extracted into a subdirectory
# named after the zip file (eg. a.zip is extracted into a/).
# Run the script multiple times until all nested zip files are
# extracted.  This is public domain software.

use strict;
use Cwd;

sub process_zip {
    my $file = shift || die;
    (my $dir = $file) =~ s,/[^/]+$,,;
    (my $bare_file = $file);
    $bare_file =~ s,.*/,,;
    my $file_nopath = $bare_file;
    $bare_file =~ s,\.zip$,,;
    my $old_dir = getcwd();
    chdir($dir) or die "Could not chdir from '$old_dir' to '$dir': $!";
    if (-d $bare_file) {
        chdir($old_dir);
        # assume zip already extracted
        return;
    }
    mkdir($bare_file);
    chdir($bare_file);
    system("unzip '../$file_nopath'");
    chdir($old_dir);
}

my $cmd = "find . -name '*.zip'";
open(my $fh, "$cmd |") or die "Error running '$cmd': $!";
while(<$fh>) {
    chomp;
    process_zip($_);
}

1

วิธีที่ง่ายที่สุดคือการใช้ atool: http://www.nongnu.org/atool/ มันเป็นสคริปต์ที่ดีมากที่ใช้โปรแกรม zip, unzip, tar, rar ฯลฯ เพื่อแยกไฟล์เก็บถาวรใด ๆ

ใช้atool -x package_name.zipเพื่อคลายซิปทั้งหมดหรือถ้าคุณต้องการใช้ในไดเรกทอรีที่มีไฟล์ zip หลายอันใช้งานง่ายforวนรอบ :

for f in *; do atool -x $f; fi(คุณจะต้องcdเข้าไปในไดเรกทอรีที่ต้องการพร้อมไฟล์ zip ก่อนใช้งาน)


atoolพฤติกรรมของที่นี่ไม่แตกต่างอย่างมากจากการเปิดเครื่องรูดฉันพูดได้ว่ามันไม่แตกไฟล์ ZIP ซ้ำ
Thomas Themel

@Thomas Themel: คุณแน่ใจหรือไม่ว่าไม่แตกไฟล์ ZIP ซ้ำ ๆ มันสามารถแยกจากไฟล์ deb tar.gz recurisvely แต่ฉันไม่มีเวลา atm เพื่อทดสอบกับคลังเก็บ zip ที่ซ้อนกัน: \

0

คุณจะต้องระมัดระวังการคลายซิปไฟล์ zip ภายในไฟล์ zip โดยอัตโนมัติ:

http://research.swtch.com/2010/03/zip-files-all-way-down.html

เป็นไปได้ที่จะรวมไฟล์ zip ที่สร้างไฟล์ zip เป็นเอาท์พุทซึ่งสร้างไฟล์ zip เป็นเอาท์พุท ฯลฯ ฯลฯ นั่นคือคุณสามารถสร้างไฟล์ zip ที่เป็น oint คงที่ของ "unzip" ของโปรแกรม

นอกจากนี้ฉันดูเหมือนจะจำได้ว่าคนที่ทำไฟล์ซิปที่จะ "ระเบิด" ซึ่งเป็นไฟล์ซิปขนาดเล็กมากจะเปิดเครื่องรูดไปยังเอาต์พุตหลายกิกะไบต์ นี่คือแง่มุมของวิธีการบีบอัด


0

อาจจะช่วยได้ (ใช้งานได้สำหรับฉัน):

function unzipAll(){

# find and count archives
archLst=`find . -type f -name "*.*ar"`
archLstSize=`echo $archLst| awk 'END{print NF}'`

# while archives exists do extract loop
while [ "$archLstSize" -gt 0 ]; do

# extract and remove all archives (found on single iteration)
for x in $archLst; do 
mv "${x}" "${x}_";
unzip "${x}_" -d "${x}" && rm "${x}_"; 
done; #EO for

# find and count archives
archLst=`find . -type f -name "*.*ar"`
archLstSize=`echo $archLst| awk 'END{print NF}'`

done #EO while

}

0

ฉันต้องการโซลูชันเช่น Giles 'จากปี 2010 ยกเว้นฉันต้องการรักษาโครงสร้างโฟลเดอร์ไม่ใช่เปิดเครื่องรูดทุกอย่างลงในไดเรกทอรีระดับบนสุด นี่คือสิ่งที่ฉันใช้กับเขาด้วยการเพิ่ม / เปลี่ยนแปลงสามบรรทัด:

#!/bin/bash
shopt -s globstar nullglob
while set -- **/*.zip; [ $# -ge 1 ]
do
    for z
    do
        ( cd -- "$(dirname "$z")" &&
            z=${z##*/} &&
            cp -- "$z" "$z".bak &&
            mkdir -- "$z"dir &&
            unzip -- "$z" -d "$z"dir &&
            rm -- "$z"
        )
    done
done

0

ชำระเงินยูทิลิตี้ที่ใช้ java นี้nzipสำหรับไฟล์ zip ที่ซ้อนกัน การแตกไฟล์และบีบอัดไฟล์ซิปที่ซ้อนกันสามารถทำได้อย่างง่ายดายโดยใช้คำสั่งต่อไปนี้

java -jar nzip.jar -c รายการ -s readme.zip

java -jar nzip.jar -c แยก -s "C: \ project \ readme.zip" -t readme

java -jar nzip.jar -c การบีบอัด -s readme -t "C: \ project \ readme.zip"

PS ฉันเป็นผู้เขียนและยินดีที่จะแก้ไขข้อบกพร่องใด ๆ ได้อย่างรวดเร็ว

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