递归解压所有子目录同时保留文件结构
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.
我是 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.