¿Cómo se descomprimen recursivamente archivos en un directorio y sus subdirectorios desde la línea de comandos de Unix?

StackOverflow https://stackoverflow.com/questions/107995

  •  01-07-2019
  •  | 
  •  

Pregunta

El unzip El comando no tiene una opción para descomprimir archivos de forma recursiva.

Si tengo la siguiente estructura de directorios y archivos:

/Mother/Loving.zip
/Scurvy/Sea Dogs.zip
/Scurvy/Cures/Limes.zip

Y quiero descomprimir todos los archivos en directorios con el mismo nombre que cada archivo:

/Mother/Loving/1.txt
/Mother/Loving.zip
/Scurvy/Sea Dogs/2.txt
/Scurvy/Sea Dogs.zip
/Scurvy/Cures/Limes/3.txt
/Scurvy/Cures/Limes.zip

¿Qué comando o comandos emitiría?

Es importante que esto no ahogue los nombres de archivos que tienen espacios.

¿Fue útil?

Solución

Si desea extraer los archivos a la carpeta respectiva, puede probar esto

find . -name "*.zip" | while read filename; do unzip -o -d "`dirname "$filename"`" "$filename"; done;

Una versión multiprocesada para sistemas que pueden manejar altas E/S:

find . -name "*.zip" | xargs -P 5 -I fileName sh -c 'unzip -o -d "$(dirname "fileName")/$(basename -s .zip "fileName")" "fileName"'

Otros consejos

Aquí hay una solución que involucra el comando buscar y un bucle while:

find . -name "*.zip" | while read filename; do unzip -o -d "`basename -s .zip "$filename"`" "$filename"; done;

Una solución que maneja correctamente todos los nombres de archivos (incluidas las nuevas líneas) y los extrae en un directorio que está en la misma ubicación que el archivo, solo que sin la extensión:

find . -name '*.zip' -exec sh -c 'unzip -o -d "${0%.*}" "$0"' '{}' ';'

Tenga en cuenta que puede hacer que maneje fácilmente más tipos de archivos (como .jar) agregándolos usando -o, p.ej.:

find . '(' -name '*.zip' -o -name '*.jar' ')' -exec ...

Puede usar buscar junto con el indicador -exec en una sola línea de comando para hacer el trabajo.

find . -name "*.zip" -exec unzip {} \;

¿Algo como gunzip usando la bandera -r?....

Viaja por la estructura de directorios de forma recursiva.Si alguno de los nombres de archivo especificados en la línea de comando es directorio, gzip descenderá al directorio y comprimirá todos los archivos que encuentre allí (o los descomprimirá en el caso de gunzip).

http://www.computerhope.com/unix/gzip.htm

Esto funciona perfectamente como queremos:

Descomprimir archivos:

find . -name "*.zip" | xargs -P 5 -I FILENAME sh -c 'unzip -o -d "$(dirname "FILENAME")" "FILENAME"'

El comando anterior no crea directorios duplicados.

Eliminar todos los archivos zip:

find . -depth -name '*.zip' -exec rm {} \;

Si está utilizando cygwin, la sintaxis es ligeramente diferente para el comando basename.

find . -name "*.zip" | while read filename; do unzip -o -d "`basename "$filename" .zip`" "$filename"; done;

Me doy cuenta de que esto es muy antiguo, pero fue uno de los primeros resultados en Google cuando buscaba una solución para algo similar, así que publicaré lo que hice aquí.Mi escenario es ligeramente diferente ya que básicamente solo quería explotar completamente un frasco, junto con todos los frascos que contiene, así que escribí las siguientes funciones bash:

function explode {
    local target="$1"
    echo "Exploding $target."
    if [ -f "$target" ] ; then
        explodeFile "$target"
    elif [ -d "$target" ] ; then
        while [ "$(find "$target" -type f -regextype posix-egrep -iregex ".*\.(zip|jar|ear|war|sar)")" != "" ] ; do
            find "$target" -type f -regextype posix-egrep -iregex ".*\.(zip|jar|ear|war|sar)" -exec bash -c 'source "<file-where-this-function-is-stored>" ; explode "{}"' \;
        done
    else
        echo "Could not find $target."
    fi
}

function explodeFile {
    local target="$1"
    echo "Exploding file $target."
    mv "$target" "$target.tmp"
    unzip -q "$target.tmp" -d "$target"
    rm "$target.tmp"
}

Nota la <file-where-this-function-is-stored> lo cual es necesario si está almacenando esto en un archivo que no se lee para un shell no interactivo como me sucedió a mí.Si está almacenando las funciones en un archivo cargado en shells no interactivos (por ejemplo, .bashrc Creo) puedes dejarlo todo. source declaración.Espero que esto ayude a alguien.

Una pequeña advertencia - explodeFile también elimina el archivo comprimido; por supuesto, puede cambiarlo comentando la última línea.

Otra solución interesante sería:

DESTINY=[Give the output that you intend]

# Don't forget to change from .ZIP to .zip.
# In my case the files were in .ZIP.
# The echo were for debug purpose.

find . -name "*.ZIP" | while read filename; do
ADDRESS=$filename
#echo "Address: $ADDRESS"
BASENAME=`basename $filename .ZIP`
#echo "Basename: $BASENAME"
unzip -d "$DESTINY$BASENAME" "$ADDRESS";
done;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top