递归解压所有子目录同时保留文件结构

Recursively unzip all subdirectories while retaining file structure

我是 bash 脚本编写的新手,我发现很难解决这个问题。

我有一个包含子目录和压缩子目录混合的父文件夹。

在这些子目录中还有更多嵌套的 zip 文件。

不仅有 .zip 文件,还有 .rar 和 .7z 文件,其中还包含嵌套 zips/rars/7zs。

我想递归地解压缩、unrar 和 un7z 我所有嵌套的子目录,直到父文件夹不再包含任何 .rar、.zip、.7zip 文件。 (这些最终需要在提取后删除)。可能有数千个子目录都处于不同的嵌套深度。您可能有压缩文件夹或压缩文件。

但是我想保留我的文件夹结构,所以解压缩的文件夹必须保留在解压缩的相同位置

我试过这个解压脚本,但它没有保留文件结构。

#!/bin/bash

while [ "`find . -type f -name '*.zip' | wc -l`" -gt 0 ]

do
    find . -type f -name "*.zip" -exec unzip -- '{}' \; -exec rm -- '{}' \;
done

                             

我想要例如:

文件夹 'a' 包含压缩文件夹 'b.zip',其中包含压缩文本文件 pear.zip(即 pear.txt 已压缩到 pear.zip a/b.zip(/pear.zip))

我希望文件夹 'a' 包含 'b' 包含 pear.txt 'a/b/pear.txt'

上面的脚本将 'b'(b 为空)和 pear 都放入文件夹 'a' 中执行脚本,这不是我想要的。例如 'a/b' 和 'a/pear.txt'

你可以试试这个:

#!/bin/bash

while :; do
    mapfile -td '' archives \
    < <(find . -type f -name '*.zip' -o -name '*.7z' -print0)

    [[ ${#archives[@]} -eq 0 ]] && break

    for i in "${archives[@]}"; do
        case $i in
            *.zip) unzip -d "$(dirname "$i")" -- "$i";;
            *.7z)  7z x "-o$(dirname "$i")" -- "$i";;
        esac
    done

    rm -rf "${archives[@]}" || break
done
  • 每个存档都按 find 列出。该列表被提取到正确的位置并删除了档案。如此重复,直到找到零个档案。

  • 您可以添加等效的 unrar 命令(我不熟悉)。

  • -o -name '*.rar'添加到find,将另一种情况添加到case。如果没有使用 unrar 指定目标目录的选项,您可以使用 cd "$(dirname "$i")" && unrar "$i".

  • 此脚本存在一些问题。特别是,如果提取失败,存档仍会被删除。否则会导致死循环。提取失败可以使用unzip ... || exit 1退出,手动处理

  • 通过计算未删除但希望没有必要的文件,既可以避免删除也可以避免无限循环。

  • 我无法正确测试它。 YMMV.