基本上,我有一组目录,这些目录不断被 .rar 文件填充,我需要能够就地提取它们,并自动删除剩余的 .(rar|rXX) 文件。我该怎么做?
注意:完成后我无法全部删除它们,必须在脚本完成一个 rar 集时将它们删除。
示例目录结构:
/
/folder1/
/file1.rar
/file1.r00
/file1.r01
/folder2/
/sub.folder1/
/file2.part001.rar (contains a directory "file2")
/file2.part002.rar
/file2.part003.rar
/sub.folder2/
/file3.rar
/file3.r00
/file3.r01
预期结果:
/
/folder1/
/file1.ext
/folder2/
/sub.folder1/
/file2/
/file2.ext
/sub.folder2/
/file3.ext
答案1
Bash 的变体:
#!/bin/bash
if [ ! -d "${1}" ]; then
printf '%s: error: mandatory argument is not a valid directory.' "${0##*/}" 1>&2
exit 1
fi
shopt -s extglob
for i in "${1}"/**/*.rar; do
cd -- "${i%/*}"
file=${i##*/}
unrar e -- "${file}" && rm -- @(${file}|${file%.rar}.r[[:digit:]][[:digit:]])
cd - >/dev/null
done
RAR 档案也可以“合法”地命名为例如myarchive.part001.rar
等等,如果存在这些类型的档案,则必须以某种方式单独处理。解决这个问题的一个务实的方法是替换
unrar e -- "${file}" && rm -- @(${file}|${file%.rar}.r[[:digit:]][[:digit:]])
和
unrar e -o- -- "${file}"
if [ $? -eq 0 -o $? -eq 10 ]; then
rm -- @(${file}|${file%.rar}.r[[:digit:]][[:digit:]])
fi
但请注意,即使出现错误代码 10(“没有要提取的文件”),这也会清除 RAR 文件,因此通常不建议以未修改的形式使用。
总而言之,最好只是将材料以存档形式存储,然后在需要使用时使用即时解压缩或类似方法。保留存档格式可能还有其他好处。
答案2
这是我凭空想出来的,所以这是未经测试的代码,但它应该能让你走上正轨。它基本上会沿着你指向的树走,寻找 .rar 文件。找到一个后,它会就地解压缩并删除原始档案,除非 unrar 返回非零值。当访问文件夹时,该函数只会调用自身,从而导致其递归。
#!/bin/bash
[[ ! -d "$1" ]] && echo "Please point me at a directory!" && exit 1
function recursively_extract_all_rars_in() {
local x=`pwd` f
cd "$1"
for f in (*); do
[[ -d "$f" ]] && recursively_extract_all_rars_in "$f"
[[ -f "$f" ]] && [[ "$f" =~ "*.rar" ]] && unrar e "$f" && rm ${f%%.*}.r??
done
cd "$x"
}
recursively_extract_all_rars_in "$1"
函数名称完全是任意的。我希望在使用它们的参数调用时,它们读起来像正确的英语。[[ -d /path ]]
如果路径存在并且是目录,则返回 true。-f
对文件执行相应的操作。[[ "string" =~ "pattern"]]
是一种允许在字符串中进行模式匹配的 bashism。它的工作原理与 glob 模式大致相同。
该行local x=pwd f
可能很神秘,但它仅定义了两个局部变量:一个名为x,用于保存pwd
,一个名为f,未初始化(它在下面的for循环中初始化,我只是在这里声明它所以它是局部的)。
如果您的功能使用,则存储pwd
并返回它cd
是一件好事(tm)。
请注意,以编程方式使用的输出ls
通常是 Bad Mojo,您应该像躲避害虫一样避开它,而使用find
。如果您的任何文件名包含空格,则在脚本中使用 ls 将会导致严重混乱。你被警告了。
中山大学
我不确定你是否可以在 Bash 中做同样的事情,但在 ZSH 中,我会把下面的内容放在.zshrc
function recursive_unrar() {
for f in **/*.rar; do
local cwd=`pwd` fbn=${f##*/}
cd "${f%/*}"
unrar e "$fbn"
rm "${fbn%%.*}.r{01..99} $fbn"
cd "$cwd"
done
}
然后只需从相应的文件夹内部调用它即可。