Unrar recursivo con eliminación a medida que avanza

Unrar recursivo con eliminación a medida que avanza

Básicamente, tengo un conjunto de directorios que se llenan constantemente con archivos .rar y necesito poder extraerlos en su lugar con la eliminación automática de los archivos .(rar|rXX) sobrantes. ¿Cómo haría esto?

Nota: No puedo eliminarlos todos una vez hecho, deben eliminarse cuando el script completa un conjunto rar.

Ejemplo de estructura de directorio:

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

Respuesta1

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

Los archivos RAR también pueden denominarse "legalmente", por ejemplo, myarchive.part001.raretc., y eso tendría que manejarse por separado de alguna manera si ese tipo de archivos existen. Una forma pragmática de resolver esto es reemplazar

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

con

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

pero tenga cuidado porque esto limpiará los archivos RAR incluso si se proporciona el código de error 10 ("No hay archivos para extraer") y, por lo tanto, generalmente no se recomienda en su forma no modificada.


Con todo, podría ser mejor simplemente tener el material almacenado en formato archivado y en su lugar utilizar la descompresión sobre la marcha o algo similar cuando desee utilizarlo. Puede haber otros beneficios al mantener el formato archivado.

Respuesta2

Estoy escribiendo esto fuera de mi cabeza, por lo que es un código no probado, pero debería llevarlo por el camino correcto. Básicamente, recorre el árbol al que apunta en busca de archivos .rar. Al encontrar uno, lo descomprimirá en su lugar y eliminará el archivo original a menos que unrar devuelva un valor distinto de cero. Al acceder a una carpeta, la función simplemente se llamará a sí misma, lo que hará que sea 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"

El nombre de la función es completamente arbitrario. Me gusta que se lean como en inglés adecuado cuando se los invoca con sus argumentos. [[ -d /path ]]devuelve verdadero si la ruta existe y es un directorio. -fhace lo correspondiente para los archivos. [[ "string" =~ "pattern"]]es un bashismo que permite la coincidencia de patrones en cadenas. Funciona principalmente como patrones globales.

La línea local x=pwd fpuede ser críptica, pero solo define dos variables locales: una llamada x, para contener el pwd, y otra llamada f, no inicializada (se inicializa en el bucle for siguiente, simplemente la declaro aquí para que sea local).

Almacenar pwdy volver a él si su función lo utiliza cdes algo bueno (tm).

Tenga en cuenta que usar la salida de lsprogramáticamente generalmente es Bad Mojo, y debe evitarlo como una plaga, a favor de find.Si alguno de los nombres de sus archivos contiene un espacio, usar ls en su script será un gran error.Usted ha sido advertido.

ZSH

No estoy seguro de que puedas hacer lo mismo en Bash, pero en ZSH, pondría lo siguiente en algún lugar de.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
}

Y luego simplemente llámalo desde dentro de la carpeta correspondiente.

información relacionada