Trích xuất các tệp zip lồng nhau


15

Tôi có nhiều kho lưu trữ zip, mỗi kho chứa một số kho lưu trữ zip. Cách tốt nhất để trích xuất đệ quy tất cả các tệp có trong kho lưu trữ zip này và kho lưu trữ zip con của nó, đó không phải là lưu trữ zip?


Ý bạn là gì khi trích xuất những thứ không phải là tệp zip? Bạn muốn sao chép chúng đến một nơi khác?
phunehehe

Tôi không tìm thấy yêu cầu của bạn rõ ràng. Tôi tìm thấy Shawn J. Goffsự giải thích của tôi về khả năng như nhau. Bạn có thể làm rõ?
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles: Xin lỗi, vâng nó hơi không rõ ràng. Tôi đã thay đổi nó một chút, hy vọng nó rõ ràng hơn bây giờ.
oadams

Tôi sẽ đăng một câu trả lời, nhưng tôi tin rằng nó nên đi như một bình luận: Lưu trữ lồng nhau làm tăng không gian bạn cần! Bạn có thể có nghĩa là định dạng tệp Zip, không chỉ gzip. mỗi tệp zip đã được nén, nén chúng lại, chỉ cần tạo thêm chi phí, tăng hiệu quả không gian cần thiết.
Polemon

Vâng, tôi đã không làm điều đó: P. Thật không may, tôi phải chịu cách phân phối tệp kỳ lạ này.
oadams

Câu trả lời:


13

Điều này sẽ trích xuất tất cả các tệp zip vào thư mục hiện tại, không bao gồm bất kỳ tệp zip nào có trong chúng.

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

Mặc dù điều này trích xuất nội dung vào thư mục hiện tại, nhưng không phải tất cả các tệp sẽ kết thúc nghiêm ngặt trong thư mục này vì nội dung có thể bao gồm các thư mục con.

Nếu bạn thực sự muốn tất cả các tệp trong thư mục hiện tại, bạn có thể chạy

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

Lưu ý: điều này sẽ ghi các tập tin nếu có hai cùng tên trong các thư mục khác nhau.

Nếu bạn muốn trích xuất đệ quy tất cả các tệp zip và các khóa có trong, phần sau đây sẽ trích xuất tất cả các tệp zip trong thư mục hiện tại và tất cả các tệp có trong chúng vào thư mục hiện tại.

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

vòng lặp while này đã giúp tôi rất nhiều trong một cuộc thi hack đạo đức, nơi họ đã chuẩn bị một tệp zip lồng nhau đi sâu 3137 cấp độ, cảm ơn!
peedee

2
bạn có thể thích biến thể này mà tôi sử dụng để trích xuất đệ quy nội dung từ các tệp lồng nhau, chiến tranh, tệp jar: gist.github.com/tyrcho/479c18795d997c201e53 Sự khác biệt chính là nó tạo một thư mục lồng nhau cho mỗi kho lưu trữ. while [ "tìm thấy . -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

Theo như tôi hiểu, bạn có kho lưu trữ zip mà bản thân chúng có chứa tài liệu lưu trữ zip và bạn muốn giải nén các khóa được lồng vào nhau bất cứ khi nào được trích xuất.

Đây là một tập lệnh bash 4 giải nén tất cả các khóa trong thư mục hiện tại và các thư mục con của nó theo cách đệ quy, xóa từng tệp zip sau khi đã được giải nén và tiếp tục miễn là có các tệp zip. Một tệp zip trong thư mục con được trích xuất liên quan đến thư mục con đó. Cảnh báo: chưa được kiểm tra, tạo bản sao lưu của các tệp gốc trước khi dùng thử hoặc thay thế rmbằng cách di chuyển tệp zip bên ngoài cây thư mục .

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

Kịch bản cũng sẽ hoạt động trong zsh nếu bạn thay thế shoptdòng bằng setopt nullglob.

Đây là một tương đương di động. Điều kiện chấm dứt hơi phức tạp vì findkhông tự động trả về trạng thái để cho biết liệu nó có tìm thấy bất kỳ tệp nào không. Cảnh báo: như trên.

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

unzipkhông làm điều này, bởi vì cách UNIX là làm một việc và làm tốt điều đó, không xử lý tất cả các trường hợp đặc biệt điên rồ trong mọi công cụ. Vì vậy, bạn cần sử dụng shell (công việc "kết nối mọi thứ lại với nhau" tốt). Điều này làm cho nó trở thành một câu hỏi lập trình và vì TẤT CẢ các câu hỏi lập trình có thể đã được trả lời trên StackOverflow, ở đây: Làm thế nào để bạn giải nén các tệp lưu trữ trong một thư mục và các thư mục con của nó từ dòng lệnh Unix?


1
Tôi chắc chắn sẽ không gọi "sử dụng shell" là câu hỏi lập trình và "shell scripting" được liệt kê trong FAQ như trên chủ đề
Michael Mrozek

Tôi không có ý ám chỉ rằng nó hoàn toàn lạc đề ở đây, tôi chỉ muốn biện minh tại sao nó lại thuộc chủ đề tại StackOverflow.
Thomas Themel

1

Tập lệnh perl này sẽ trích xuất từng tệp .zip vào thư mục con riêng của nó. Chạy tập lệnh nhiều lần để xử lý các tệp zip lồng nhau. Nó không xóa các tệp .zip sau khi giải nén nhưng bạn có thể thực hiện thay đổi đó bằng cách thêm một cuộc gọi hủy liên kết ().

#!/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

Cách dễ nhất là sử dụng atool: http://www.nongnu.org/atool/ Đây là một tập lệnh rất tốt sử dụng các chương trình zip, unzip, tar, rar, vv để trích xuất bất kỳ kho lưu trữ nào.

Sử dụng atool -x package_name.zipđể giải nén tất cả hoặc nếu bạn muốn sử dụng nó trong thư mục có nhiều tệp zip sử dụng đơn giảnfor vòng lặp :

for f in *; do atool -x $f; fi(bạn sẽ phải cdvào thư mục mong muốn với các tệp zip trước khi sử dụng tệp này).


atoolHành vi của chúng ở đây không khác biệt đáng kể so với giải nén Tôi nói, nó cũng không trích xuất đệ quy các tệp ZIP.
Thomas Themel

@Thomas Themel: Bạn có chắc chắn rằng nó không trích xuất đệ quy các tệp ZIP? Nó có thể trích xuất từ ​​các tệp deb tar.gz nhưng tôi không có thời gian để kiểm tra nó với kho lưu trữ zip lồng nhau: \

0

Bạn sẽ muốn cẩn thận tự động giải nén các tệp zip bên trong các tệp zip:

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

Bạn có thể tạo một tệp zip tạo tệp zip làm đầu ra, tạo ra tệp zip làm đầu ra, v.v. Đó là, bạn có thể tạo một tệp zip là một loại thuốc mỡ cố định của "giải nén" chương trình.

Ngoài ra, tôi dường như nhớ lại những người tạo các tệp zip sẽ "phát nổ", đó là một tệp zip rất nhỏ sẽ giải nén thành nhiều gigabyte đầu ra. Đây là một khía cạnh của phương pháp nén.


0

Có lẽ điều này sẽ giúp (làm việc cho tôi):

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

Tôi cần một giải pháp như Giles 'từ năm 2010, ngoại trừ tôi cần bảo toàn cấu trúc thư mục, không giải nén mọi thứ vào thư mục cấp cao nhất. Đây là của tôi với ba dòng được thêm / thay đổi:

#!/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

Kiểm tra tiện ích dựa trên java này tra nzip cho các tệp zip lồng nhau. Trích xuất và nén các khóa lồng nhau có thể được thực hiện dễ dàng bằng cách sử dụng các lệnh sau

danh sách java -jar nzip.jar -c readme.zip

java -jar nzip.jar -c giải nén -s "C: \ project \ readme.zip" -t readme

java -jar nzip.jar -c nén -s readme -t "C: \ project \ readme.zip"

Tái bút Tôi là tác giả và sẽ vui lòng sửa bất kỳ lỗi nào một cách nhanh chóng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.