Estrazione di file zip nidificati


15

Ho numerosi archivi zip, ognuno dei quali contiene un numero di archivi zip. Qual è il modo migliore per estrarre in modo ricorsivo tutti i file contenuti in questo archivio zip e nei suoi archivi zip figlio, che non sono archivi zip stessi?


cosa intendi per estrazione di cose che non sono file zip? ti va di copiarli in un altro posto?
phunehehe,

Non trovo chiare le tue esigenze. Trovo che Shawn J. Goff e la mia interpretazione siano ugualmente probabili. Potresti chiarire?
Gilles 'SO- smetti di essere malvagio' il

@Gilles: Scusa, sì, non è stato chiaro. L'ho cambiato un po ', si spera che ora sia più chiaro.
oadams,

Avevo intenzione di pubblicare una risposta, ma credo che dovrebbe andare come un commento: gli archivi nidificati aumentano lo spazio di cui hai bisogno! Probabilmente intendi il formato del file Zip, non solo gzip. ogni file zip è già compresso, comprimendolo di nuovo, crea solo più overhead, aumentando efficacemente lo spazio necessario.
polemon

Sì, non l'ho fatto: P. Purtroppo sono sottoposto a questo bizzarro modo di distribuire file.
oadams,

Risposte:


13

Ciò estrarrà tutti i file zip nella directory corrente, escludendo tutti i file zip in essi contenuti.

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

Anche se questo estrae i contenuti nella directory corrente, non tutti i file finiranno rigorosamente in questa directory poiché i contenuti possono includere sottodirectory.

Se in realtà volevi tutti i file rigorosamente nella directory corrente, puoi eseguire

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

Nota: questo bloccherà i file se ce ne sono due con lo stesso nome in directory diverse.

Se si desidera estrarre in modo ricorsivo tutti i file zip e le zip contenute all'interno, quanto segue estrae tutti i file zip nella directory corrente e tutte le zip contenute al loro interno nella directory corrente.

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

questo mentre loop mi ha aiutato molto in una competizione di hacking etico in cui avevano preparato un file zip nidificato con una profondità di 31337 livelli, grazie!
Peedee,

2
ti potrebbe piacere questa variante che uso per estrarre ricorsivamente contenuti da file nidificati di orecchio, guerra, vaso: gist.github.com/tyrcho/479c18795d997c201e53 La differenza principale è che crea una cartella nidificata per ciascun archivio. while [ "trova . -type f -name '*.? ar' | wc -l" -gt 0 ]; do find -type f -name "*.?ar" -exec mkdir -p '{}.dir' \; -exec unzip -d '{}.dir' -- '../{}' \; -exec rm -- '{}' \;; done
Michel Daviot,

4

Per quanto ho capito, hai archivi zip che a loro volta contengono archivi zip e vorresti decomprimere le zip annidate ogni volta che ne viene estratta una.

Ecco uno script bash 4 che decomprime tutte le zip nella directory corrente e nelle sue sottodirectory ricorsivamente, rimuove ogni file zip dopo che è stato decompresso e continua finché ci sono file zip. Un file zip in una sottodirectory viene estratto rispetto a quella sottodirectory. Avvertenza: non testato, eseguire un backup dei file originali prima di provarlo o sostituirlo rmspostando il file zip all'esterno dell'albero della directory .

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

Lo script funzionerà anche in zsh se si sostituisce la shoptriga con setopt nullglob.

Ecco un equivalente portatile. La condizione di terminazione è un po 'complicata perché findnon restituisce spontaneamente uno stato per indicare se ha trovato dei file. Attenzione: come sopra.

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

1

unzipnon lo fa, perché il modo UNIX è fare una cosa e farlo bene, non gestire tutti i casi speciali pazzi in ogni strumento. Pertanto, è necessario utilizzare la shell (che svolge bene il compito di "legare le cose insieme"). Questo lo rende una domanda di programmazione e poiché a TUTTE le possibili domande di programmazione è stata data una risposta su StackOverflow, qui: Come decomprimere in modo ricorsivo gli archivi in ​​una directory e nelle sue sottodirectory dalla riga di comando di Unix?


1
Sicuramente non chiamerei "usare la shell" una domanda di programmazione e "shell scripting" è elencato nelle FAQ come argomento
Michael Mrozek

Non intendevo implicare che qui fosse fuori tema, volevo solo giustificare il motivo per cui è in argomento su StackOverflow.
Thomas Themel,

1

Questo script perl estrae ogni file .zip nella sua sottodirectory. Esegui lo script più di una volta per gestire i file zip nidificati. Non elimina i file .zip dopo l'estrazione, ma è possibile apportare tale modifica aggiungendo una chiamata 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

Il modo più semplice è usare atool: http://www.nongnu.org/atool/ È un ottimo script che usa programmi zip, unzip, tar, rar ecc per estrarre qualsiasi archivio.

Utilizzare atool -x package_name.zipper decomprimerli tutti o se si desidera utilizzarlo nella directory con molti file zip, utilizzare un forciclo semplice :

for f in *; do atool -x $f; fi(dovrai accedere alla cddirectory desiderata con i file zip prima di utilizzarlo).


atoolIl comportamento qui non differisce in modo significativo dalla decompressione, direi, non estrae nemmeno in modo ricorsivo i file ZIP.
Thomas Themel,

@Thomas Themel: sei sicuro che non estragga ricorsivamente file ZIP? Può estrarre dai file deb tar.gz in modo ricorsivo ma non ho tempo atm per testarlo con archivi zip nidificati: \

0

Ti consigliamo di fare attenzione a decomprimere automaticamente i file zip all'interno dei file zip:

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

È possibile creare un file zip che produca un file zip come output, che produce un file zip come output, ecc. Ecc. Cioè, è possibile creare un file zip che sia un unguento fisso di "decomprimere" il programma.

Inoltre, mi sembra di ricordare alle persone che creano file zip che "esploderebbero", ovvero un file zip molto piccolo che si decomprimerebbe in multi-gigabyte di output. Questa è una sfaccettatura del metodo di compressione.


0

Forse questo aiuterà (ha funzionato per me):

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

Avevo bisogno di una soluzione come quella di Giles del 2010, tranne che per preservare la struttura delle cartelle, non decomprimere tutto nella directory di livello superiore. Ecco la mia opinione su di lui con tre righe aggiunte / modificate:

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

Dai un'occhiata a questa utility basata su Java nzip per i file zip nidificati. L'estrazione e la compressione di zip nidificate può essere eseguita facilmente utilizzando i seguenti comandi

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"

PS. Sono l'autore e sarò felice di correggere rapidamente eventuali bug.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.