如何从Unix命令行recursion地解压目录及其子目录中的归档文件?

unzip命令没有用于recursion解压缩存档的选项。

如果我有以下目录结构和档案:

 /Mother/Loving.zip
 /坏血病/海狗.zip
 /Scurvy/Cures/Limes.zip

我想把所有的档案解压到与每个档案同名的目录中:

 /Mother/Loving/1.txt
 /Mother/Loving.zip
 /坏血病/海狗/ 2.txt
 /坏血病/海狗.zip
 /Scurvy/Cures/Limes/3.txt
 /Scurvy/Cures/Limes.zip

我会发出什么命令或命令?

重要的是,这不会窒息其中有空格的文件名。

如果你想提取文件到相应的文件夹,你可以试试这个

 find . -name "*.zip" | while read filename; do unzip -o -d "`dirname "$filename"`" "$filename"; done; 

可处理高I / O的系统的多处理版本:

 find . -name "*.zip" | xargs -P 5 -I fileName sh -c 'unzip -o -d "$(dirname "fileName")/$(basename -s .zip "fileName")" "fileName"' 

以下是一个涉及find命令和while循环的解决scheme:

 find . -name "*.zip" | while read filename; do unzip -o -d "`basename -s .zip "$filename"`" "$filename"; done; 

一个正确处理所有文件名(包括换行符)并解压缩到与文件位于同一位置的目录的解决scheme,只是删除了扩展名:

 find . -name '*.zip' -exec sh -c 'unzip -o -d "${0%.*}" "$0"' '{}' ';' 

请注意,通过使用-o添加它们,您可以轻松地处理更多文件types(如.jar ),例如:

 find . '(' -name '*.zip' -o -name '*.jar' ')' -exec ... 

您可以在一个命令行中使用find和-exec标志来完成这项工作

 find . -name "*.zip" -exec unzip {} \; 

像使用-r标志的gunzip?

recursion地旅行目录结构。 如果命令行中指定的任何文件名都是目录,则gzip将下降到目录中并压缩它在其中find的所有文件(或在gunzip中解压缩它们)。

http://www.computerhope.com/unix/gzip.htm

如果您使用的是cygwin,则basename命令的语法略有不同。

 find . -name "*.zip" | while read filename; do unzip -o -d "`basename "$filename" .zip`" "$filename"; done; 

我意识到这是非常古老的,但是当我在寻找类似的解决scheme时,它是Google上的第一个点击,所以我会发布我在这里做的。 我的情况稍有不同,因为我基本上只是想完全炸开一个jar子,以及其中包含的所有jar子,所以我写了下面的bash函数:

 function explode { local target="$1" echo "Exploding $target." if [ -f "$target" ] ; then explodeFile "$target" elif [ -d "$target" ] ; then while [ "$(find "$target" -type f -regextype posix-egrep -iregex ".*\.(zip|jar|ear|war|sar)")" != "" ] ; do find "$target" -type f -regextype posix-egrep -iregex ".*\.(zip|jar|ear|war|sar)" -exec bash -c 'source "<file-where-this-function-is-stored>" ; explode "{}"' \; done else echo "Could not find $target." fi } function explodeFile { local target="$1" echo "Exploding file $target." mv "$target" "$target.tmp" unzip -q "$target.tmp" -d "$target" rm "$target.tmp" } 

注意<file-where-this-function-is-stored> ,如果你正在将它存储在一个文件中,而这个文件并不是为非交互式shell读取的,就像我碰巧那样。 如果您将函数存储在加载在非交互式shell上的文件中(例如,我相信.bashrc ),则可以删除整个source语句。 希望这会帮助某人。

有一点警告 – explodeFile也会删除ziped文件,你当然可以通过注释掉最后一行来改变它。

另一个有趣的解决scheme是:

 DESTINY=[Give the output that you intend] # Don't forget to change from .ZIP to .zip. # In my case the files were in .ZIP. # The echo were for debug purpose. find . -name "*.ZIP" | while read filename; do ADDRESS=$filename #echo "Address: $ADDRESS" BASENAME=`basename $filename .ZIP` #echo "Basename: $BASENAME" unzip -d "$DESTINY$BASENAME" "$ADDRESS"; done;