提取嵌套的 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 -- '{}' . \;

注意:如果不同目录中有两个同名文件,这将破坏文件。

如果要递归地提取所有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。

这是一个 bash 4 脚本,它递归地解压缩当前目录及其子目录中的所有 zip,解压缩后删除每个 zip 文件,并且只要有 zip 文件就继续解压。子目录中的 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

答案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 文件作为输出,等等。也就是说,您可以制作一个 zip 文件,它是“解压缩”程序的固定点。

另外,我似乎记得人们制作的 zip 文件会“爆炸”,即一个非常小的 zip 文件会解压缩为数 GB 的输出。这是压缩方法的一个方面。

相关内容