Рекурсивный Unrar с удалением по мере выполнения

Рекурсивный Unrar с удалением по мере выполнения

По сути, у меня есть набор каталогов, которые постоянно заполняются .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 также могут быть «законно» названы eg 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

Однако следует помнить, что при этом будут удалены файлы RAR, даже если выдается код ошибки 10 («Нет файлов для извлечения»), поэтому этот метод обычно не рекомендуется использовать в неизмененном виде.


В общем, может быть лучше просто хранить материал в архивной форме и вместо этого использовать декомпрессию на лету или что-то подобное, когда вы хотите его использовать. Могут быть и другие преимущества сохранения архивного формата.

решение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"]]является башизмом, который позволяет сопоставлять шаблоны в строках. Он работает в основном так же, как шаблоны glob.

Строка local x=pwd fможет показаться непонятной, но она просто определяет две локальные переменные: одну с именем x, для хранения pwd, и одну с именем f, неинициализированную (она инициализируется в цикле for ниже, я просто объявляю ее здесь, чтобы она была локальной).

Сохранение pwdи возврат к нему, если ваша функция его использует, cd— это Хорошая Вещь (tm).

Обратите внимание, что использование вывода lsпрограммного кода, как правило, является плохим приемом, и вам следует избегать его как вредителя, отдавая предпочтение 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
}

А затем просто вызовите его из соответствующей папки.

Связанный контент