Unrar Recursivo com Exclusão conforme progride

1
Basicamente, eu tenho um conjunto de diretórios que estão constantemente sendo preenchidos com .rar, e eu preciso ser capaz de extraí-los no lugar com a exclusão automática dos arquivos left (. | rar | rXX). Como eu iria sobre isso?

Observação: não é possível excluir todos eles depois de concluídos, eles precisam ser excluídos, pois o script conclui um conjunto de 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
    
por Jharwood 03.06.2012 / 22:36

2 respostas

3

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 "legalmente" nomeados, por ex. myarchive.part001.rar e assim por diante, e isso teria que ser tratado separadamente de alguma forma se esses tipos de arquivos existirem. Uma maneira pragmática de resolver isso é 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, não for geralmente recomendado em sua forma não modificada.

Em suma, pode ser melhor simplesmente ter o material armazenado na forma arquivada e, em vez disso, usar a descompactação dinâmica ou algo semelhante quando você quiser usá-lo. Pode haver outros benefícios em manter o formato arquivado.

    
por 04.06.2012 / 10:26
1

Estou escrevendo isso em primeiro lugar, por isso é um código não testado, mas isso deve colocá-lo no caminho certo. Basicamente percorre a árvore para a qual você aponta, procurando por arquivos .rar. Ao encontrar um, ele será descompactado no lugar e excluirá o arquivo original, a menos que o unrar retorne diferente de zero. Ao bater em uma pasta, a função só irá chamar a si mesma, fazendo com que seja 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. Eu gosto de lê-los como bom inglês quando invocado com seus argumentos. [[ -d /path ]] retornará verdadeiro se o caminho existir e for um diretório. -f faz o correspondente para arquivos. [[ "string" =~ "pattern"]] é uma base que permite a correspondência de padrões em strings. Funciona basicamente como padrões glob.

A linha local x=pwd f pode ser enigmática, mas define apenas duas variáveis locais: uma chamada x, para conter o pwd e outra chamada f, não inicializada (é inicializada no loop for abaixo, apenas declaro aqui, então é local).

Armazenando o pwd e retornando a ele se sua função usar cd é uma coisa boa (tm).

Por favor, note que usar a saída de ls programaticamente é geralmente Bad Mojo, e você deve evitá-lo como a praga, em favor de find . Se qualquer um dos seus nomes de arquivo contiver um espaço, usar o comando ls no seu script vai atrapalhar bastante. Você foi avisado.

ZSH

Não tenho certeza se você pode fazer a mesma coisa no Bash, mas no ZSH, coloquei o seguinte em algum lugar em .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, em seguida, basta chamá-lo de dentro da pasta correspondente.

    
por 03.06.2012 / 23:57

Tags