Extrair arquivos zip aninhados

13

Eu tenho inúmeros arquivos zip, cada um contendo vários arquivos zip. Qual é a melhor maneira de extrair recursivamente todos os arquivos contidos neste arquivo zip e em seus arquivos ZIP compactados, que não são arquivos zip em si?

    
por oadams 27.11.2010 / 10:56

9 respostas

11

Isso extrairá todos os arquivos zip no diretório atual, excluindo todos os arquivos zip contidos neles.

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

Embora isso extraia o conteúdo para o diretório atual, nem todos os arquivos terminarão estritamente nesse diretório, pois o conteúdo pode incluir subdiretórios.

Se você realmente queria todos os arquivos estritamente no diretório atual, você pode executar

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

Nota: isso irá destruir arquivos se houver dois com o mesmo nome em diretórios diferentes.

Se você quiser recursivamente extrair todos os arquivos zip e os zips contidos, o seguinte extrai todos os arquivos zip no diretório atual e todos os zips contidos neles no diretório atual.

while [ "'find . -type f -name '*.zip' | wc -l'" -gt 0 ]; do find -type f -name "*.zip" -exec unzip -- '{}' \; -exec rm -- '{}' \;; done
    
por 27.11.2010 / 14:23
3

Tanto quanto eu entendo, você tem arquivos zip que contêm arquivos zip, e você gostaria de descompactar zip aninhados sempre que um é extraído.

Aqui está um script bash 4 que descompacta todos os zips no diretório atual e em seus subdiretórios de forma recursiva, remove cada arquivo zip depois de ter sido descompactado e continua enquanto houver arquivos zip. Um arquivo zip em um subdiretório é extraído em relação a esse subdiretório. Aviso: não testado, faça um backup dos arquivos originais antes de testá-lo ou substitua rm movendo o arquivo zip para fora da árvore de diretórios .

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

O script também funcionará em zsh se você substituir a linha shopt por setopt nullglob .

Aqui está um equivalente portátil. A condição de finalização é um pouco complicada porque find não retorna espontaneamente um status para indicar se encontrou algum arquivo. Aviso: como acima.

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

unzip não faz isso, porque o modo UNIX é fazer uma coisa e fazer isso bem, não lidar com todos os casos especiais malucos em todas as ferramentas. Assim, você precisa usar o shell (que faz o trabalho de "amarrar as coisas" bem). Isso torna uma questão de programação e, como TODAS as possíveis perguntas de programação foram respondidas no StackOverflow, aqui: Como você recursivamente descompacta arquivos em um diretório e seus subdiretórios a partir da linha de comando do Unix?

    
por 27.11.2010 / 14:06
1

Este script perl extrairá cada arquivo .zip em seu próprio subdiretório. Execute o script mais de uma vez para manipular arquivos zip aninhados. Ele não exclui os arquivos .zip após a extração, mas você pode fazer essa alteração adicionando uma chamada 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($_);
}
    
por 16.12.2011 / 14:34
1

A maneira mais fácil é usar o atool: link É um script muito bom que usa programas zip, unzip, tar, rar etc. para extrair qualquer arquivo.

Use atool -x package_name.zip para descompactar todos eles ou se você quiser usá-lo no diretório com muitos arquivos zip use for loop simples:

for f in *; do atool -x $f; fi (você terá que cd no diretório desejado com arquivos zip antes de usar isso).

    
por 28.11.2010 / 17:33
0

Você desejará ter cuidado ao descompactar arquivos zip automaticamente dentro de arquivos zip:

link

É possível criar um arquivo zip que produza um arquivo zip como saída, o que produz um arquivo zip como saída, etc. etc. etc. Ou seja, você pode criar um arquivo zip que seja um método fixo de "descompactar" o programa.

Além disso, parece que me lembro de pessoas fazendo arquivos zip que "explodiriam", ou seja, um arquivo zip muito pequeno descompactaria para vários gigabytes de saída. Essa é uma faceta do método de compactação.

    
por 29.11.2010 / 16:22
0

Talvez isso ajude (funcionou para mim):

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

}
    
por 11.01.2016 / 19:59
0

Eu precisava de uma solução como a do Giles de 2010, exceto que eu precisava preservar a estrutura de pastas, não descompactar tudo no diretório de nível superior. Aqui está a minha opinião sobre ele com três linhas adicionadas / alteradas:

#!/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
    
por 04.10.2017 / 16:12
0

Faça o check-out deste utilitário baseado em java nzip para arquivos zip aninhados. Extrair e compactar zips aninhados pode ser feito facilmente usando os seguintes comandos

java -jar nzip.jar -c lista -s readme.zip

java -jar nzip.jar -c extrair -s "C: \ project \ readme.zip" -t readme

java -jar nzip.jar -c compress -s readme -t "C: \ projeto \ readme.zip"

PS. Eu sou o autor e ficarei feliz em corrigir quaisquer erros rapidamente.

    
por 02.05.2018 / 19:55