Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从Unix命令行递归解压目录及其子目录中的存档?_Unix_Recursion_Spaces_Unzip - Fatal编程技术网

如何从Unix命令行递归解压目录及其子目录中的存档?

如何从Unix命令行递归解压目录及其子目录中的存档?,unix,recursion,spaces,unzip,Unix,Recursion,Spaces,Unzip,unzip命令没有递归解压缩存档的选项 如果我有以下目录结构和档案: /Mother/Loving.zip /Scurvy/Sea Dogs.zip /Scurvy/Cures/Limes.zip /母亲/Loving.zip /坏血病/海狗.zip /坏血病/治愈/酸橙。zip 我想将所有档案解压到与每个档案同名的目录中: /Mother/Loving/1.txt /Mother/Loving.zip /Scurvy/Sea Dogs/2.txt /Scurvy/Sea Dogs.zip /S

unzip
命令没有递归解压缩存档的选项

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

/Mother/Loving.zip /Scurvy/Sea Dogs.zip /Scurvy/Cures/Limes.zip /母亲/Loving.zip /坏血病/海狗.zip /坏血病/治愈/酸橙。zip 我想将所有档案解压到与每个档案同名的目录中:

/Mother/Loving/1.txt /Mother/Loving.zip /Scurvy/Sea Dogs/2.txt /Scurvy/Sea Dogs.zip /Scurvy/Cures/Limes/3.txt /Scurvy/Cures/Limes.zip /母亲/Loving/1.txt /母亲/Loving.zip /坏血病/海狗/2.txt /坏血病/海狗.zip /坏血病/Cures/Limes/3.txt /坏血病/治愈/酸橙。zip 我会发出什么命令


重要的是,这不会阻塞包含空格的文件名。

这里有一个解决方案,可以将所有zip文件提取到工作目录,并涉及find命令和while循环:

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

像gunzip一样使用-r标志

递归地遍历目录结构。如果命令行上指定的任何文件名是目录,gzip将下降到目录中并压缩它在那里找到的所有文件(或者在gunzip的情况下解压缩它们)


您可以在单个命令行中使用find和-exec标志来执行此任务

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

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

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

如果要将文件解压缩到相应的文件夹,可以尝试以下操作

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"'

我意识到这是非常古老的,但它是我在谷歌上寻找类似解决方案的第一批点击,所以我将在这里发布我所做的。我的场景略有不同,因为我基本上只想完全分解一个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"
}
函数爆炸{
本地目标=“1美元”
echo“爆炸$target”
如果[-f“$target”];则
分解文件“$target”
elif[-d“$target”];然后
而[“$(查找“$target”-type f-regextype posix egrep-iregex”.*\(zip | jar | ear | war | sar)!=”;do
查找“$target”-type f-regextype posix egrep-iregex“*\(zip | jar | ear | war | sar)“-exec bash-c'source”“;explode”{}”;
完成
其他的
echo“找不到$target。”
fi
}
函数文件{
本地目标=“1美元”
echo“爆炸文件$target”
mv“$target”“$target.tmp”
解压-q“$target.tmp”-d“$target”
rm“$target.tmp”
}
请注意
,如果您将其存储在一个文件中,而该文件不是像我碰巧那样为非交互式shell读取的,则需要该文件。如果您将函数存储在加载到非交互式Shell上的文件中(例如,
.bashrc
,我相信),您可以删除整个
source
语句。希望这能帮助一些人


有一点警告-
explodeFile
也会删除压缩文件,您当然可以通过注释掉最后一行来更改它。

这是一种解决方案,它可以正确处理所有文件名(包括换行符)并提取到与文件位于同一位置的目录中,只需删除扩展名即可:

find . -iname '*.zip' -exec sh -c 'unzip -o -d "${0%.*}" "$0"' '{}' ';'
请注意,通过使用
-o
,您可以轻松地使其处理更多的文件类型(例如
.jar
),例如:

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

另一个有趣的解决办法是:

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;

这完全符合我们的要求:

解压缩文件:

find . -name "*.zip" | xargs -P 5 -I FILENAME sh -c 'unzip -o -d "$(dirname "FILENAME")" "FILENAME"'
find . -depth -name '*.zip' -exec rm {} \;
上面的命令不会创建重复的目录

删除所有zip文件:

find . -name "*.zip" | xargs -P 5 -I FILENAME sh -c 'unzip -o -d "$(dirname "FILENAME")" "FILENAME"'
find . -depth -name '*.zip' -exec rm {} \;
在安装了Info zip的
zip
软件包后,对我来说效果很好:

sudo apt install -y zip
上面的安装是针对Debian/Ubuntu/Mint的。对于其他Linux发行版, 请参阅下面的第二个参考资料

参考文献:


这会将所有内容解压到当前目录中,而不是相对于每个子目录。它也不会解压缩到与每个归档文件同名的目录中。读者需要注意的是,-exec只允许在命令中使用{},通过调用sh并将{}赋值给变量来解决这个问题。在这种情况下,我认为这无关紧要。我的发现(GNU findutils 4.4.0)允许我多次使用{}。。。cloud@thunder:~/tmp/files$find-exec echo{}{}\/a./a./b./b./c./c./d./d./e./e./f./f./g./gSee,它使用
-exec
包括
-d
。请注意,在调用
sh
时必须小心,以确保像
"; rm-rf/没有被执行。他特别提到的是zip文件,而不是gzip文件。这是正确的做法,因为它保留了完整的目录结构!注意-这不会按要求将文件解压缩到与存档同名的目录中。我不知道xargs有多核支持!事实上,它不能解压到单独的文件夹,这意味着它不能完全回答问题。此外,如果给定文件夹中的多个zip文件包含同名文件,例如
results.log
,则当您尝试将同一文件的多个副本解压缩到一个文件夹中时,会出现问题。我想在Cygwin身上试试。它看起来像
-d“'dirname…
part应该处理这个问题,但它对我不起作用。出于某种原因,第一个示例对我和emlai有相同的问题,所有解压缩文件都放在zip文件所在的目录中。然而,第二种方法,多线程方法,不仅工作得更快,而且还将每个zip文件的文件放在以zip文件命名的目录中。完美的注意-这会将所有zip文件解压缩到工作目录!当您请求相对解压缩时。看,嗯,似乎并没有将它们全部提取到工作目录AFAICT。我正在使用OS X El Capitan 10.11.6中的解压5.52。结果似乎与Vivek的结果相同。接受他的答案,因为它也展示了如何利用多核!长文件路径如何。。。贝昂