it-swarm-es.tech

Extracción de archivos Zip anidados

Tengo numerosos archivos Zip, cada uno de los cuales contiene varios archivos Zip. ¿Cuál es la mejor manera de extraer de forma recursiva todos los archivos contenidos en este archivo Zip y sus archivos Zip secundarios, que no son archivos Zip en sí mismos?

15
oadams

Esto extraerá todos los archivos Zip en el directorio actual, excluyendo los archivos zip que contengan.

find . -type f -name '*.Zip' -exec unzip -- '{}' -x '*.Zip' \;

Aunque esto extrae el contenido al directorio actual, no todos los archivos terminarán estrictamente en este directorio ya que el contenido puede incluir subdirectorios.

Si realmente deseaba todos los archivos estrictamente en el directorio actual, puede ejecutar

find . -type f -mindepth 2 -exec mv -- '{}' . \;

Nota: esto afectará a los archivos si hay dos con el mismo nombre en diferentes directorios.

Si desea extraer de forma recursiva todos los archivos Zip y los archivos comprimidos que contiene, lo siguiente extrae todos los archivos Zip del directorio actual y todos los archivos comprimidos que contienen en el directorio actual.

while [ "`find . -type f -name '*.Zip' | wc -l`" -gt 0 ]
do
    find . -type f -name "*.Zip" -exec unzip -- '{}' \; -exec rm -- '{}' \;
done
13
Shawn J. Goff

Por lo que tengo entendido, tiene archivos Zip que a su vez contienen archivos Zip, y le gustaría descomprimir las cremalleras anidadas cada vez que se extrae una.

Aquí hay una secuencia de comandos de bash 4 que descomprime todas las cremalleras en el directorio actual y sus subdirectorios de forma recursiva, elimina cada archivo Zip después de que se ha descomprimido y sigue funcionando mientras haya archivos Zip. Un archivo Zip en un subdirectorio se extrae en relación con ese subdirectorio. Advertencia: sin probar, haga una copia de seguridad de los archivos originales antes de probarlo o reemplace rm moviendo el archivo Zip fuera del árbol de directorios.

shopt -s globstar nullglob
while set -- **/*.Zip; [ $# -ge 1 ] do
  for z; do
    ( cd -- "$(dirname "$z")" &&
      z=${z##*/} &&
      unzip -- "$z" &&
      rm -- "$z"
    )
  done
done

El script también funcionará en zsh si reemplaza la línea shopt por setopt nullglob.

Aquí tienes un equivalente portátil. La condición de terminación es un poco complicada porque find no devuelve espontáneamente un estado para indicar si ha encontrado algún archivo. Advertencia: como arriba.

while [ -n "$(find . -type f -name '*.Zip' -exec sh -c '
    cd "${z%/*}" &&
    z=${z##*/} &&
    unzip -- "$z" 1>&2 &&
    rm -- "$z" &&
    echo 1
')" ]; do :; done

unzip no hace esto, porque la forma de UNIX es hacer una cosa y hacerlo bien, no manejar todos los casos especiales locos en cada herramienta. Por lo tanto, necesita usar el Shell (que hace el trabajo de "unir las cosas" bien). Esto lo convierte en una pregunta de programación, y dado que TODAS las posibles preguntas de programación han sido respondidas en StackOverflow, aquí: ¿Cómo descomprime de forma recursiva archivos en un directorio y sus subdirectorios desde la línea de comandos de Unix?

1
Thomas Themel

La forma más fácil es usar una herramienta: http://www.nongnu.org/atool/ Es un muy buen script que usa programas Zip, descomprimir, tar, rar, etc. para extraer cualquier archivo.

Utilizar atool -x package_name.Zip para descomprimirlos todos o si desea usarlo en un directorio con muchos archivos Zip, use el bucle simple for:

for f in *; do atool -x $f; fi (tendrá que cd en el directorio deseado con archivos Zip antes de usar esto).

1
user2648

Este script de Perl extraerá cada archivo .Zip en su propio subdirectorio. Ejecute el script más de una vez para manejar archivos Zip anidados. No elimina los archivos .Zip después de la extracción, pero puede realizar ese cambio agregando una llamada a unlink ().

#!/usr/bin/Perl -w

# This script unzips all .Zip files it finds in the current directory
# and all subdirectories.  Contents are extracted into a subdirectory
# named after the Zip file (eg. a.Zip is extracted into a/).
# Run the script multiple times until all nested Zip files are
# extracted.  This is public domain software.

use strict;
use Cwd;

sub process_Zip {
    my $file = shift || die;
    (my $dir = $file) =~ s,/[^/]+$,,;
    (my $bare_file = $file);
    $bare_file =~ s,.*/,,;
    my $file_nopath = $bare_file;
    $bare_file =~ s,\.Zip$,,;
    my $old_dir = getcwd();
    chdir($dir) or die "Could not chdir from '$old_dir' to '$dir': $!";
    if (-d $bare_file) {
        chdir($old_dir);
        # assume Zip already extracted
        return;
    }
    mkdir($bare_file);
    chdir($bare_file);
    system("unzip '../$file_nopath'");
    chdir($old_dir);
}

my $cmd = "find . -name '*.Zip'";
open(my $fh, "$cmd |") or die "Error running '$cmd': $!";
while(<$fh>) {
    chomp;
    process_Zip($_);
}
1
John

Verifique esto Java utilidad basada en nzip para archivos Zip anidados. La extracción y compresión de cremalleras anidadas se puede hacer fácilmente usando los siguientes comandos

Java -jar nzip.jar -c list -s readme.Zip

Java -jar nzip.jar -c extract -s "C:\project\readme.Zip" -t readme

Java -jar nzip.jar -c compress -s readme -t "C:\project\readme.Zip"

PD. Soy el autor y estaré encantado de corregir cualquier error rápidamente.

0
user930412

Necesitaba una solución como la de Giles de 2010, excepto que necesitaba preservar la estructura de la carpeta, no descomprimir todo en el directorio de nivel superior. Aquí está mi opinión sobre la suya con tres líneas agregadas/modificadas:

#!/bin/bash
shopt -s globstar nullglob
while set -- **/*.Zip; [ $# -ge 1 ]
do
    for z
    do
        ( cd -- "$(dirname "$z")" &&
            z=${z##*/} &&
            cp -- "$z" "$z".bak &&
            mkdir -- "$z"dir &&
            unzip -- "$z" -d "$z"dir &&
            rm -- "$z"
        )
    done
done
0
steaknchips

Deberá tener cuidado al descomprimir automáticamente los archivos Zip dentro de los archivos Zip:

http://research.swtch.com/2010/03/Zip-files-all-way-down.html

Es posible crear un archivo Zip que produzca un archivo Zip como salida, que produzca un archivo Zip como salida, etc., etc. Es decir, puede crear un archivo Zip que sea un componente fijo de "descomprimir" el programa.

Además, creo recordar a personas que creaban archivos Zip que "explotaban", es decir, un archivo Zip muy pequeño se descomprime en varios gigabytes de salida. Ésta es una faceta del método de compresión.

0
Bruce Ediger

Quizás esto ayude (funcionó para mí):

function unzipAll(){

# find and count archives
archLst=`find . -type f -name "*.*ar"`
archLstSize=`echo $archLst| awk 'END{print NF}'`

# while archives exists do extract loop
while [ "$archLstSize" -gt 0 ]; do

# extract and remove all archives (found on single iteration)
for x in $archLst; do 
mv "${x}" "${x}_";
unzip "${x}_" -d "${x}" && rm "${x}_"; 
done; #EO for

# find and count archives
archLst=`find . -type f -name "*.*ar"`
archLstSize=`echo $archLst| awk 'END{print NF}'`

done #EO while

}
0
user151061