我有许多zip档案,每个档案都包含许多zip档案。递归提取此zip存档及其子zip存档中包含的所有文件的最佳方法是什么,而不是zip存档本身?
我有许多zip档案,每个档案都包含许多zip档案。递归提取此zip存档及其子zip存档中包含的所有文件的最佳方法是什么,而不是zip存档本身?
Answers:
这会将所有压缩文件解压缩到当前目录中,其中不包含其中的任何压缩文件。
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
while [ "
找 。型f -name'*。?ar'| wc -l" -gt 0 ]; do find -type f -name "*.?ar" -exec mkdir -p '{}.dir' \; -exec unzip -d '{}.dir' -- '../{}' \; -exec rm -- '{}' \;; done
据我了解,您拥有本身包含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
unzip
不会这样做,因为UNIX方式是做一件事情并且做得很好,而不是在每个工具中都处理所有疯狂的特殊情况。因此,您需要使用外壳程序(可以很好地完成“将事物捆绑在一起”的工作)。这使它成为一个编程问题,并且由于在StackOverflow上已经回答了所有可能的编程问题,因此,这里:如何从Unix命令行递归解压缩目录及其子目录中的归档?
该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($_);
}
您需要注意自动在zip文件内部解压缩zip文件:
http://research.swtch.com/2010/03/zip-files-all-way-down.html
可以压缩生成一个zip文件作为输出的zip文件,生成一个zip文件作为输出的等等,依此类推。也就是说,您可以使zip文件成为程序“解压缩”的固定点。
此外,我似乎还记得人们制作的zip文件会“爆炸”,这是一个很小的zip文件,可以解压缩到数GB的输出。这是压缩方法的一个方面。
也许这会有所帮助(为我工作):
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
}
我需要一个像2010年的Giles一样的解决方案,除了我需要保留文件夹结构,而不是将所有内容都解压缩到顶层目录中。这是我对他的看法,添加/更改了三行:
#!/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