93 votes

Comment décompresser récursivement des archives dans un répertoire et ses sous-répertoires à partir de la ligne de commande Unix ?

Les unzip n'a pas d'option pour décompresser récursivement les archives.

Si j'ai la structure de répertoire et les archives suivantes :

/Mother/Loving.zip
/Scurvy/Sea Dogs.zip
/Scurvy/Cures/Limes.zip

Et je veux décompresser toutes les archives dans des répertoires portant le même nom que chaque archive :

/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

Quel(s) ordre(s) devrais-je donner ?

Il est important que cela ne s'arrête pas aux noms de fichiers contenant des espaces.

2voto

Quelque chose comme gunzip en utilisant le drapeau -r ? ....

Parcourir la structure du répertoire de manière récursive. Si l'un des noms de fichiers spécifiés sur la ligne de commande est un répertoire, gzip descend dans le répertoire et compresse tous les fichiers qu'il y trouve (ou les décompresse dans le cas de gunzip ).

http://www.computerhope.com/unix/gzip.htm

2voto

Si vous utilisez cygwin, la syntaxe est légèrement différente pour la commande basename.

find . -name "*.zip" | while read filename; do unzip -o -d "`basename "$filename" .zip`" "$filename"; done;

1voto

Thor84no Points 2969

Je me rends compte que ce document est très ancien, mais il figurait parmi les premiers résultats de Google lorsque j'ai cherché une solution à un problème similaire, et je vais donc publier ce que j'ai fait ici. Mon scénario est légèrement différent, car je voulais simplement faire exploser un bocal, ainsi que tous les bocaux qu'il contient, et j'ai donc écrit les fonctions bash suivantes :

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"
}

Notez que les <file-where-this-function-is-stored> ce qui est nécessaire si vous le stockez dans un fichier qui n'est pas lu par un shell non interactif comme c'était mon cas. Si vous stockez les fonctions dans un fichier chargé sur des shells non-interactifs (par exemple, .bashrc Je crois que vous pouvez laisser tomber l'ensemble source déclaration. J'espère que cela aidera quelqu'un.

Un petit avertissement - explodeFile supprime également le fichier zippé, vous pouvez bien sûr changer cela en commentant la dernière ligne.

0voto

Prometheus Points 102

Une autre solution intéressante serait la suivante :

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;

0voto

Hongbo Miao Points 9333

Vous pouvez également parcourir en boucle chaque fichier zip en créant chaque dossier et en décompressant le fichier zip.

for zipfile in *.zip; do
  mkdir "${zipfile%.*}"
  unzip "$zipfile" -d "${zipfile%.*}"
done

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X