ネストされたzipファイルの抽出

ネストされたzipファイルの抽出

私は多くのzipアーカイブを持っており、各zipアーカイブには複数のzipアーカイブが含まれています。このzipアーカイブとそのサブzipアーカイブ(それ自体はzipアーカイブではない)に含まれるすべてのファイルを再帰的に抽出する最良の方法は何ですか?

答え1

これにより、含まれているzipファイルを除いて、すべてのzipファイルが現在のディレクトリに抽出されます。

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

これにより、コンテンツは現在のディレクトリに抽出されますが、コンテンツにサブディレクトリが含まれる可能性があるため、すべてのファイルがそのディレクトリに厳密に配置されるわけではありません。

実際にすべてのファイルを現在のディレクトリにのみ配置するには、次のように実行できます。

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

注:異なるディレクトリに同じ名前の2つのファイルがある場合、ファイルは破損します。

すべてのzipファイルとその中に含まれるすべてのzipを再帰的に抽出したい場合、次のコマンドは現在のディレクトリのすべてのzipファイルとその中に含まれるすべてのzipを現在のディレクトリに抽出します。

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

答え2

私が理解したように、あなたのzipアーカイブ自体にはzipアーカイブが含まれており、入れ子になったzipを解凍したときに入れ子になったzipを解凍したいと思います。

これは、現在のディレクトリとサブディレクトリにあるすべてのzipの圧縮を繰り返し解凍し、解凍した後に各zipファイルを削除し、zipファイルがある限り引き続き解凍するbash 4スクリプトです。サブディレクトリのzipファイルは、そのサブディレクトリに基づいて抽出されます。警告:テストされていません。元のファイルをバックアップまたは試す前に、rmzipファイルを移動して置き換えてください。ディレクトリツリーの外部

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

この行をに置き換えると、shoptスクリプトはzshでも実行されますsetopt 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

答え3

このPerlスクリプトは、各.zipファイルを独自のサブディレクトリに抽出します。ネストされたzipファイルを処理するには、スクリプトを数回実行します。抽出後に.zipファイルは削除されませんが、unlink()呼び出しを追加して変更できます。

#!/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($_);
}

答え4

zipファイル内でzipファイルを自動的に解凍するときは注意してください。

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

zipファイルを出力として生成するzipファイルを生成し、出力としてzipファイルを生成するなどの操作を実行できます。つまり、「unzip」プログラムの固定点であるzipファイルを作成できます。

また、人々が「爆発」するzipファイルを作成したことを覚えているようです。つまり、非常に小さなzipファイルは解凍され、数ギガバイトの出力になります。これが圧縮方法の一側面です。

関連情報