Créer un répertoire si l'archive zip contient plusieurs fichiers

8

Si une archive contient plusieurs fichiers dans le répertoire racine, je voudrais créer un répertoire nommé d'après le nom du fichier (sans extension). Si une archive ne contient qu'un répertoire, je voudrais simplement l'extraire. Supposons que j'ai les archives suivantes:

# file: withdir.zip
somedir/alpha
somedir/beta
somedir/gamma

Si je l'extrait dans le répertoire courant, j'aimerais qu'il soit simplement extrait ( unzip withdir.zip):

somedir/alpha
somedir/beta
somedir/gamma

Supposons maintenant l'archive suivante:

# file: nodir.zip
alpha
beta
gamma

Lorsque je cours, unzip nodir.zipje finis par encombrer le répertoire actuel avec les trois fichiers:

alpha
beta
gamma

Je préfère courir unzip -d nodir nodir.zip:

nodir/alpha
nodir/beta
nodir/gamma

Si j'utilise nautilus et clique droit sur "Extraire ici". Il se comporte exactement comme il se doit. Mais malheureusement, je n'ai pas trouvé de commutateur de ligne de commande pour unzipou 7zqui donne le même comportement. Comment y parvenir? Y a-t-il d'autres outils que je peux utiliser à la place (pas d'interface graphique)?

Marco
la source

Réponses:

7

Je ferais quelque chose comme ça (syntaxe zsh):

unz() (
  tmp=$(TMPDIR=. mktemp -d -- ${${argv[-1]:t:r}%.tar}.XXXXXX) || exit
  print -r >&2 "Extracting in $tmp"
  cd -- $tmp || exit
  [[ $argv[-1] = /* ]] || argv[-1]=../$argv[-1]
  (set -x; "$@"); ret=$?
  files=(*(ND[1,2]))
  case $#files in
    (0) print -r >&2 "No file created"
        rmdir -v "../$tmp";;
    (1) mv -v -- $files .. && rmdir -v ../$tmp;;
    (*) mv -vT ../$tmp ../$tmp:r;;
  esac && exit $ret
)

C'est:

  1. créer un répertoire dans tous les cas
  2. exécutez la commande
  3. selon le nombre de fichiers générés par la commande:
    • supprimer ce répertoire (s'il n'a créé aucun fichier)
    • s'il n'a créé qu'un seul fichier / répertoire, déplacez-le d'un niveau vers le haut et jetez notre répertoire
    • sinon, essayez de supprimer la chaîne aléatoire de la fin de notre répertoire temporaire.

De cette façon, vous pouvez faire:

unz unzip foo.zip
unz tar xf foo.tar.gz

Il suppose que le dernier argument de la commande d'extraction est le fichier à extraire. Il suppose également des outils GNU pour les -voptions. Sur les systèmes non GNU, vous pouvez les supprimer et éventuellement effectuer la journalisation à la main. mv -Test également spécifique à GNU, et consiste à forcer la mvtentative de changement de nom uniquement.

Stéphane Chazelas
la source
3

Comme unzipet les 7zdeux ont un commutateur de sortie dans un répertoire donné, vous pouvez créer un script simple, que les contrôles, le nombre de fichiers dans la racine de l'archive et ajoute ensuite l'interrupteur en cas de besoin.

Avec 7z, c'est plus facile, car il a le -sltcommutateur, ce qui rend la sortie plus lisible par la machine. Pour chaque fichier du zip, la sortie contiendra une Path = ...ligne. Les fichiers à la racine ne doivent en contenir aucun /dans la valeur.

Un script simple que j'ai écrit pour décompresser les fichiers de cette façon:

#!/bin/sh
for archive in "$@"; do
    # count files in root dir
    rootfiles=$(7z l -slt "${archive}" | grep -c 'Path = [^/]*$')

    # add -o switch, if more than one file in root
    # checks for >2, because path of the zip file itself is listed too
    if [ $rootfiles -gt 2 ]; then
        filename=${archive##*/}
        rootname=${filename%.*}
        opt="-o${rootname}"
    fi

    #unpack
    7z x "${opt}" "${archive}"
done

Edit: le script fonctionne maintenant aussi avec zip

cratère2150
la source
Ce script ne fonctionne pas comme prévu. Il crée un répertoire withdirpour l'archive withdir.zipbien qu'il ne contienne qu'un seul répertoire à la racine car grep -c "Folder = -"retourne 3.
Marco
ah, le dossier semble être différent pour les fichiers zip. Je vais chercher une solution
crater2150
@Marco: J'ai changé le script et l'ai testé avec des fichiers zip, il ne crée maintenant le dossier qu'en cas de besoin
crater2150
3

patool gère différents types d'archives et crée un sous-répertoire au cas où l'archive contient plusieurs fichiers pour éviter d'encombrer le répertoire de travail avec les fichiers extraits.

Créer une archive

patool create archive.zip somedirectory

Extraire l'archive

patool extract archive.zip

Pour obtenir une liste des formats pris en charge, utilisez patool formats.

Marco
la source
1

Vous pouvez également utiliser unar , qui crée un répertoire conteneur par défaut lorsqu'il existe deux fichiers de niveau supérieur ou plus:

$ touch 1 2
$ zip a.zip 1 2
  adding: 1 (stored 0%)
  adding: 2 (stored 0%)
$ unzip -l a.zip
Archive:  a.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
        0  04-29-14 10:56   1
        0  04-29-14 10:56   2
 --------                   -------
        0                   2 files
$ unar a.zip
a.zip: Zip
  1  (0 B)... OK.
  2  (0 B)... OK.
Successfully extracted to "a".
$ ls a
1 2

Ajouter -dpour toujours créer un répertoire conteneur.

Lri
la source