我有很多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 的输出。这是压缩方法的一个方面。