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?
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?
Risposte:
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
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
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 rm
spostando 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 shopt
riga con setopt nullglob
.
Ecco un equivalente portatile. La condizione di terminazione è un po 'complicata perché find
non 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
unzip
non 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?
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($_);
}
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.zip
per decomprimerli tutti o se si desidera utilizzarlo nella directory con molti file zip, utilizzare un for
ciclo semplice :
for f in *; do atool -x $f; fi
(dovrai accedere alla cd
directory desiderata con i file zip prima di utilizzarlo).
atool
Il comportamento qui non differisce in modo significativo dalla decompressione, direi, non estrae nemmeno in modo ricorsivo i file ZIP.
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.
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
}
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
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.