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


15

多数のzipアーカイブがあり、それぞれに多数のzipアーカイブが含まれています。このzipアーカイブとその子zipアーカイブに含まれるすべてのファイルを再帰的に抽出する最良の方法は何ですか?


zipファイルではないものを抽出するとはどういう意味ですか?別の場所にコピーしたいですか?
プネヘヘ

あなたの要件が明確ではないと思います。私はショーンJ.ゴフ同様の可能性についての私の解釈を見つけます。明確にできますか?
ジル「SO-悪であるのをやめなさい」

@Gilles:すみません、それは少し不明瞭でした。私はそれを少し変更しましたが、願わくばもっと明確になりました。
oadams

私は答えを投稿するつもりでしたが、コメントとして行くべきだと思います:ネストされたアーカイブは必要なスペースを増やします!おそらくgzipではなく、Zipファイル形式を意味します。すべてのzipファイルはすでに圧縮されており、それらを再度圧縮すると、オーバーヘッドが増加するだけで、必要なスペースが効果的に増えます。
ポールモン

ええ、私はそれをしませんでした:P。残念ながら、私はファイルを配布するこの奇妙な方法にさらされています。
oadams

回答:


13

これにより、すべての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

このwhileループは、倫理的なハッキング競技で31337レベルの深さのネストされたzipファイルを準備してくれたおかげで、とても助けてくれました!
ピーディー

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
ミシェル・ダビオ

4

私が理解している限り、zipアーカイブにはそれ自体にzipアーカイブが含まれており、ネストされたzipを解凍するたびに解凍したいと考えています。

以下は、現在のディレクトリとそのサブディレクトリ内のすべてのzipを再帰的に解凍し、各zipファイルを解凍後に削除し、zipファイルがある限り継続するbash 4スクリプトです。サブディレクトリ内のzipファイルは、そのサブディレクトリを基準にして抽出されます。警告:未テスト。元のファイルを試す前にバックアップを作成するかrm、zipファイルをディレクトリツリーの外に移動して置き換えます。

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

1

unzipUNIXの方法では、すべてのツールですべてのクレイジーな特殊なケースを処理するのではなく、1つのことを行い、それを適切に行うためです。したがって、シェルを使用する必要があります(これは「物事を結び付ける」という仕事をうまく行います)。これはプログラミングの質問になります。また、StackOverflowでプログラミングに関するすべての質問に回答しているので、ここで:Unixコマンドラインからディレクトリとそのサブディレクトリにアーカイブを再帰的に解凍するにはどうすればよいですか?


1
私は間違いなく上のトピックとして、よくある質問に記載されているプログラミングの質問、および「シェルスクリプト」「シェルを使用して、」呼び出すことはありません
マイケルMrozek

ここではまったくトピック外であると言うつもりはありませんでしたが、StackOverflowでなぜトピック外であるのかを正当化したかっただけです。
トーマスセメル

1

この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($_);
}

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; ficdこれを使用する前に、zipファイルで目的のディレクトリに移動する必要があります)。


atoolここでの振る舞いは、私が言うようにunzipと大きく異なりません。再帰的にZIPファイルも抽出しません。
トーマスセメル

@Thomas Themel:再帰的にZIPファイルを抽出しないのですか?debファイルtar.gzから抽出できますが、ネストされたzipアーカイブでテストする時間がありません。\

0

zipファイル内のzipファイルの自動解凍には注意が必要です。

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

出力としてzipファイルを生成するzipファイルを作成すること、出力としてzipファイルを生成することなどが可能です。つまり、プログラムを「解凍」する固定ointであるzipファイルを作成できます。

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


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年のソリューションが必要でしたが、最上位のディレクトリにすべてを解凍するのではなく、フォルダー構造を保持する必要がありました。3行追加/変更した彼の見解を以下に示します。

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

ネストされたzipファイルについては、このJavaベースのユーティリティnzip確認してください。ネストされたzipの抽出と圧縮は、次のコマンドを使用して簡単に実行できます。

java -jar nzip.jar -c list -s readme.zip

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

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

PS。私は作者であり、バグをすぐに修正できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.