Unrar recursivo com exclusão à medida que avança

Unrar recursivo com exclusão à medida que avança

Basicamente, eu tenho um conjunto de diretórios que são constantemente preenchidos com .rar e preciso ser capaz de extraí-los no local com exclusão automática dos arquivos .(rar|rXX) restantes. Como eu faria isso?

Nota: não posso excluir todos eles depois de concluído, eles devem ser excluídos conforme o script completa um conjunto rar.

Exemplo de estrutura de diretório:

/
/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

Resultado esperado:

/
/folder1/
        /file1.ext
/folder2/
        /sub.folder1/
                    /file2/
                          /file2.ext
        /sub.folder2/
                    /file3.ext

Responder1

Variante para 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

Os arquivos RAR também podem ser nomeados "legalmente", por exemplo, myarchive.part001.rare assim por diante, e isso teria que ser tratado separadamente de alguma forma se esses tipos de arquivos existirem. Uma forma pragmática de resolver isto é substituir

unrar e -- "${file}" && rm -- @(${file}|${file%.rar}.r[[:digit:]][[:digit:]])

com

unrar e -o- -- "${file}"
if [ $? -eq 0 -o $? -eq 10 ]; then
    rm -- @(${file}|${file%.rar}.r[[:digit:]][[:digit:]])
fi

mas tenha cuidado, pois isso limpará os arquivos RAR mesmo se o código de erro 10 ("Nenhum arquivo para extrair") for fornecido e, portanto, geralmente não é recomendado em sua forma não modificada.


Resumindo, pode ser melhor simplesmente armazenar o material no formato arquivado e, em vez disso, usar a descompressão instantânea ou algo semelhante quando quiser usá-lo. Pode haver outros benefícios em manter o formato arquivado.

Responder2

Estou escrevendo isso de cabeça, então é um código não testado, mas deve colocar você no caminho certo. Basicamente, ele percorre a árvore para a qual você aponta, procurando por arquivos .rar. Ao encontrar um, ele irá descompactá-lo e excluir o arquivo original, a menos que unrar retorne diferente de zero. Ao acessar uma pasta, a função apenas chamará a si mesma, tornando-a recursiva.

#!/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"

O nome da função é completamente arbitrário. Gosto que eles sejam lidos como um inglês adequado quando invocados com seus argumentos. [[ -d /path ]]retorna verdadeiro se o caminho existir e for um diretório. -ffaz o correspondente para arquivos. [[ "string" =~ "pattern"]]é um bashismo que permite a correspondência de padrões em strings. Funciona principalmente como padrões glob.

A linha local x=pwd fpode ser enigmática, mas apenas define duas variáveis ​​locais: uma chamada x, para conter o pwd, e outra chamada f, não inicializada (é inicializada no loop for abaixo, acabei de declará-la aqui para que seja local).

Armazenar pwde retornar a ele se sua função usar cdé uma coisa boa (tm).

Observe que usar a saída de lsprogramaticamente é geralmente Bad Mojo, e você deve evitá-lo como uma praga, em favor de find.Se algum dos seus nomes de arquivo contiver um espaço, usar ls no seu script irá estragar tudo.Você foi avisado.

ZSH

Não tenho certeza se você pode fazer a mesma coisa no Bash, mas no ZSH, eu colocaria o seguinte em algum lugar.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
}

E então basta chamá-lo de dentro da pasta correspondente.

informação relacionada