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

StackOverflow https://stackoverflow.com/questions/107995

  •  01-07-2019
  •  | 
  •  

Question

La commande unzip n'a pas d'option pour décompresser les archives de manière récursive.

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 souhaite 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

Quelle commande ou quelles commandes devrais-je lancer?

Il est important que cela n’étouffe pas les noms de fichiers contenant des espaces.

Était-ce utile?

La solution

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

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

Version multi-traitée pour les systèmes pouvant 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"'

Autres conseils

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;

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

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

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

.
find . '(' -name '*.zip' -o -name '*.jar' ')' -exec ...

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

.
find . -name "*.zip" -exec unzip {} \;

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

Parcourez la structure de répertoires de manière récursive. Si l'un des noms de fichier 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 trouvera (ou les décompressera dans le cas de gunzip).

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

Cela fonctionne parfaitement comme nous voulons:

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.

Supprimer tous les fichiers zip:

find . -depth -name '*.zip' -exec rm {} \;

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;

Je réalise que c'est très vieux, mais c'était l'un des premiers hits sur Google quand je cherchais une solution à quelque chose de similaire, alors je vais poster ce que j'ai fait ici. Mon scénario est légèrement différent, car je voulais fondamentalement juste exploser complètement un bocal, ainsi que tous les bocaux 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"
}

Notez le <file-where-this-function-is-stored> qui est nécessaire si vous stockez ceci 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 l'intégralité de l'instruction source. J'espère que cela aidera quelqu'un.

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

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;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top