web-dev-qa-db-fra.com

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

La commande 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:

/Mère/Aimer.Zip 
/Scorbut/Sea Dogs.Zip 
/Scorbut/Cures/Limes.Zip 

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

/Mère/Aimer/1.txt 
/Mère/Aimer.Zip 
/Scorbut/Sea Dogs/2.txt 
/Scorbut/Sea Dogs.Zip 
/Scorbut/Cures/Limes/3.txt 
/Scorbut/Cures/Limes.Zip 

Quelle commande ou commandes émettrais-je?

Il est important que cela ne s'étouffe pas sur les noms de fichiers qui contiennent des espaces.

56
chuckrector

Si vous souhaitez extraire les fichiers dans le dossier correspondant, vous pouvez essayer ceci

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

Une version multi-traitement pour les systèmes qui peuvent gérer des E/S élevées:

find . -name "*.Zip" | xargs -P 5 -I fileName sh -c 'unzip -o -d "$(dirname "fileName")/$(basename -s .Zip "fileName")" "fileName"'
89
Vivek Thomas

Voici une solution qui implique la commande find et une boucle while:

find . -name "*.Zip" | while read filename; do unzip -o -d "`basename -s .Zip "$filename"`" "$filename"; done;
32
chuckrector

Une solution qui gère correctement tous les noms de fichiers (y compris les sauts de ligne) et extrait dans un répertoire qui se trouve au même emplacement que le fichier, juste avec l'extension supprimée:

find . -name '*.Zip' -exec sh -c 'unzip -o -d "${0%.*}" "$0"' '{}' ';'

Notez que vous pouvez facilement lui faire gérer plus de types de fichiers (tels que .jar) en les ajoutant à l'aide de -o, par exemple.:

find . '(' -name '*.Zip' -o -name '*.jar' ')' -exec ...
16
robinst

Vous pouvez utiliser find avec l'indicateur -exec dans une seule ligne de commande pour faire le travail

find . -name "*.Zip" -exec unzip {} \;
5
Jahangir

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

Parcourez 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 sont des répertoires, gzip descendra dans le répertoire et compressera tous les fichiers qu'il y trouve (ou les décompressera dans le cas de gunzip).

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

2
essexboyracer

Cela fonctionne parfaitement comme nous le souhaitons:

Décompressez les fichiers:

find . -name "*.Zip" | xargs -P 5 -I FILENAME sh -c 'unzip -o -d "$(dirname "FILENAME")" "FILENAME"'

La commande ci-dessus ne crée pas de répertoires en double.

Supprimez tous les fichiers Zip:

find . -depth -name '*.Zip' -exec rm {} \;
1
Prabhav

Une autre solution intéressante serait:

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;
0
Prometheus

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;
0
Crutis

Je me rends compte que c'est très ancien, mais c'était parmi les premiers succès sur Google lorsque je cherchais une solution à quelque chose de similaire, alors je posterai ce que j'ai fait ici. Mon scénario est légèrement différent car je voulais simplement exploser complètement un pot, ainsi que tous les pots qu'il contient, 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"
}

Noter la <file-where-this-function-is-stored> ce qui est nécessaire si vous stockez cela dans un fichier qui n'est pas lu pour un shell non interactif comme je l'ai été. Si vous stockez les fonctions dans un fichier chargé sur des shells non interactifs (par exemple, .bashrc Je crois) vous pouvez supprimer la totalité de l'instruction source. J'espère que cela aidera quelqu'un.

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

0
Thor84no