Come fare in modo ricorsivo decomprimere gli archivi in una directory e le sue sottodirectory da linea di comando Unix?
Domanda
Il unzip
il comando non dispone di un'opzione per ricorsivamente decomprimere archivi.
Se ho la seguente struttura di directory e gli archivi:
/Mother/Loving.zip /Scurvy/Sea Dogs.zip /Scurvy/Cures/Limes.zip
E voglio decomprimere tutti gli archivi in una directory con lo stesso nome, come ogni archivio:
/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
Quale comando o i comandi dovrei problema?
È importante che questo non soffocare su di nomi di file che contengono spazi.
Soluzione
Se si desidera estrarre i file nella cartella che si può provare questo
find . -name "*.zip" | while read filename; do unzip -o -d "`dirname "$filename"`" "$filename"; done;
Un multi-versione elaborata per i sistemi in grado di gestire velocità di I/O:
find . -name "*.zip" | xargs -P 5 -I fileName sh -c 'unzip -o -d "$(dirname "fileName")/$(basename -s .zip "fileName")" "fileName"'
Altri suggerimenti
Ecco una soluzione che prevede il comando trova e un ciclo while:
find . -name "*.zip" | while read filename; do unzip -o -d "`basename -s .zip "$filename"`" "$filename"; done;
Una soluzione che gestisce correttamente tutti i nomi di file (compresi i ritorni a capo) e gli estratti in una cartella che si trova nella stessa posizione del file con l'estensione rimosso:
find . -name '*.zip' -exec sh -c 'unzip -o -d "${0%.*}" "$0"' '{}' ';'
Nota che si può facilmente rendere gestire più tipi di file (ad esempio .jar
) con l'aggiunta di loro utilizzando -o
, ad es.:
find . '(' -name '*.zip' -o -name '*.jar' ')' -exec ...
Si potrebbe utilizzare trovare insieme con l'-exec bandiera in una singola riga di comando per fare il lavoro
find . -name "*.zip" -exec unzip {} \;
Qualcosa di simile gunzip utilizzando l'opzione-r bandiera?....
Di viaggio, la struttura di directory in modo ricorsivo.Se uno qualsiasi dei nomi di file specificato sulla riga di comando sono directory, gzip scenderà in directory e comprimere tutti i file che trova (o si decomprimono in caso di gunzip ).
Questo funziona perfettamente come vogliamo:
Decomprimere i file:
find . -name "*.zip" | xargs -P 5 -I FILENAME sh -c 'unzip -o -d "$(dirname "FILENAME")" "FILENAME"'
Comando di cui sopra non creare duplicati di directory.
Rimuovere tutti i file zip:
find . -depth -name '*.zip' -exec rm {} \;
Se stai usando cygwin, la sintassi è leggermente diversa per il basename comando.
find . -name "*.zip" | while read filename; do unzip -o -d "`basename "$filename" .zip`" "$filename"; done;
Mi rendo conto che non è molto vecchio, ma è stato tra i primi su Google, quando ero alla ricerca di una soluzione a qualcosa di simile, quindi vi posto quello che ho fatto qui.La mia situazione è leggermente diversa in quanto in pratica ho solo voluto completamente esplodere un vaso, insieme con tutti i barattoli in esso contenute, così ho scritto le seguenti funzioni 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 il <file-where-this-function-is-stored>
che è necessario se si memorizza questo in un file che non viene letto per una shell non interattiva, come mi è capitato di essere.Se si memorizza le funzioni in un file caricato non le shell interattive (ad esempio, .bashrc
Io credo) è possibile eliminare l'intero source
istruzione.Spero che questo possa aiutare qualcuno.
Un po ' di attenzione - explodeFile
elimina anche il ziped file, ovviamente si può cambiare, che commentando l'ultima riga.
Un'altra soluzione interessante sarebbe:
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;