递归解压并删除

递归解压并删除

基本上,我有一组目录,这些目录不断被 .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
}

然后只需从相应的文件夹内部调用它即可。

相关内容