Comment puis-je forcer unzip / zip à ne pas créer de sous-répertoire lorsque je l'extraye?

19

Selon la façon dont un fichier zip est créé, il extrait parfois tous les fichiers directement et parfois il extrait les fichiers dans un sous-répertoire.

Si ce dernier est vrai, comment puis-je forcer la unzipcommande à "ignorer" ce répertoire de premier niveau?

Exemple:

cd /tmp
wget http://omeka.org/files/omeka-1.5.1.zip
mkdir omeka
unzip omeka-1.5.1.zip -d omeka/
cd omeka/
ll

Ce que je reçois c'est /tmp/omeka/omeka-1.5.1/:

total 12
drwxr-xr-x 3 root root 4096 2012-05-08 18:44 ./
drwxrwxrwt 6 root root 4096 2012-05-08 18:44 ../
drwxr-xr-x 5 root root 4096 2012-04-20 14:54 omeka-1.5.1/

Ce que je veux, c'est des fichiers extraits /tmp/omeka/, (un niveau supérieur et aucun numéro de version inclus dans la structure du répertoire)

/tmp/omeka/(files)

Je sais que je peux utiliser l' -joption de "chemins indésirables" mais je veux conserver la structure du sous-répertoire, mais pas la structure du répertoire de niveau supérieur. Comment puis-je faire ceci?

cwd
la source
ps: Je suis conscient que je peux extraire puis mvles fichiers, mais je voulais voir s'il y avait un moyen de le faire directement à partir de la commande de décompression
cwd
Je n'en connais pas. Mais si le nom de fichier correspond toujours (à l'exception de l'extension) au nom du répertoire, il est assez simple de scripter le changement de nom du répertoire extrait.
Mat
3
Je vois ce que vous essayez de faire, mais je ne le recommanderais pas. Supprimer le numéro de version de vos sources de projet est une mauvaise idée; vous devez simplement extraire normalement et utiliser un ln -s si vous voulez un nom plus court sans informations de version. De cette façon, vous savez toujours quelle version vous utilisez et pouvez facilement mettre à jour vers une nouvelle version en changeant le lien.
Burton Samograd
@BurtonSamograd - ce serait idéal, mais je suis toujours curieux de savoir s'il existe un moyen efficace de le faire, car certains logiciels, prenez Wordpress comme exemple, placent chaque version dans un /wordpress/répertoire (pas de numéro de version) à l'intérieur du fichier zip. C'est bien unzipainsi, mvmais le fait de ne pas avoir le contrôle de cela et de le faire en deux étapes m'a toujours un peu énervé. Heureusement, Wordpress est également disponible en version .tar.gz:)
cwd
Essayezcd /tmp/omeka && ln -s -T . omeka-1.5.1
James Youngman

Réponses:

4

Utilisez un système de fichiers FUSE qui vous permet de parcourir des archives comme des répertoires, tels que AVFS . Utilisez cppour extraire les fichiers dans le répertoire de votre choix.

mountavfs
cp -Rp ~/.avfs/tmp/omeka-1.5.1.zip\#/omeka-1.5.1 omeka

Puisque nous supposons qu'il existe un seul répertoire de haut niveau dans l'archive, vous pouvez le raccourcir en

cp -Rp ~/.avfs/tmp/omeka-1.5.1.zip\#/* omeka
Gilles 'SO- arrête d'être méchant'
la source
@Giles, vous êtes l'expert qui vient répondre à toutes les questions auxquelles personne d'autre ne peut répondre, donc je suppose que c'est vraiment la seule façon de le faire. J'espérais unzipavoir un peu de magie pour le faire, comme spécifier les fichiers à extraire comme */*, que je pourrais utiliser sans installer un autre utilitaire, mais je suppose que non. Merci. +1
cwd
6

Si votre fichier zip ne contient pas de structure de répertoire ou si vous n'avez pas besoin de le conserver, vous pouvez utiliser ceci:

cd /tmp
wget http://omeka.org/files/omeka-1.5.1.zip
unzip -j omeka-1.5.1.zip -d omeka
cd omeka
ll
Eneko Alonso
la source
3

Ce script n'est pas robuste, mais fonctionne dans les cas simples:

...
dest=omeka
unzip omeka-1.5.1.zip -d $dest/

if [ `ls $dest | wc -l` == 1 ]; then
  subdir=`ls $dest`
  mv $dest/$subdir/* $dest/
  rmdir $dest/$subdir
fi

Il vérifie simplement s'il y a exactement un sous-répertoire, et si c'est le cas, en déplace tout, puis le supprime.

Steve Bennett
la source
2

Je viens de m'inscrire aujourd'hui, je ne peux donc pas voter pour @SteveBennet et je ne peux pas y ajouter de commentaire.

Sur la base de sa réponse, j'ai créé une fonction récursive comme celle-ci:

...

shopt -s dotglob # To include hidden files in the move command

function moveSub {
  local dest=$1
  if [ `ls $dest | wc -l` == 1 ]; then
    local subdir=`ls $dest`
    moveSub "$dest/$subdir"
    mv $dest/$subdir/* $dest/
    rmdir $dest/$subdir
  fi
}

moveSub "$dest"

Tout comme @SteveBennet l'a dit: ce script n'est pas robuste, mais fonctionne dans les cas simples.

J'espère que c'est utile.

elysch
la source
1

Besoin ressemble à une patch --strip=noption

Il serait souhaitable d'avoir une option comme patch --strip=number(ou -pnumber) qui coupe les numbercomposants du chemin au début (réf. Comparaison et fusion de fichiers: répertoires de correctifs ).

Autre solution, applicabilité

A défaut, il existe une autre solution, un peu hackish mais qui marche. Dans mon cas, je voulais écraser un répertoire plein de fichiers existants avec le contenu d'un zip, sans extraire le zip complet au préalable.

Lorsque cette solution fonctionne et que la solution de @ Gilles est disponible, cette dernière fonctionnera également. Pourtant, cette solution ne nécessite pas la disponibilité d'un système de fichiers FUSE.

Comment faire

En supposant que vous connaissez le répertoire supplémentaire, dans votre cas omeka-1.5.1, vous pouvez le faire:

mkdir omeka
ln -s . omeka/omeka-1.5.1 # create a symlink that redirects output
unzip omeka-1.5.1.zip -d omeka/
rm omeka/omeka-1.5.1 # remote symlink

unzipva essayer de décompresser omeka-1.5.1ce qui est en fait un lien symbolique vers contenant dir. En conséquence, les fichiers atterriront omekadirectement.

Variantes possibles

Vous pouvez imaginer des variantes pour rediriger une ou plusieurs parties d'une hiérarchie depeer.

ln -s ../myfoo omeka/omeka-1.5.1/foo
ln -s ../../mybarxyzzy omeka/omeka-1.5.1/subdir/bar

Conclusion

Cette solution est quelque peu spécifique, mais elle a ses cas d'utilisation et je viens de l'utiliser.

Stéphane Gourichon
la source
Excellente solution si vous connaissez le chemin!
grepsedawk
Le chemin peut être sondé en listant d'abord le contenu du zip, par exemple avec unzip -l. Cela pourrait même être automatisé à l'aide d'un script qui représente une partie du chemin commun.
Stéphane Gourichon
Oh totalement, c'est juste une tonne plus facile si vous connaissez le chemin. J'ai joué avec unzip -l pendant un petit moment mais c'était un peu plus grep / sed / awk que je ne le pensais, donc j'ai reculé.
grepsedawk
zipinfo -1pourrait être un bon début. Quel est votre cas d'utilisation?
Stéphane Gourichon
github.com/grepsedawk/wow-config/blob/… dans ce cas, je connais le répertoire :)
grepsedawk
1

Vous souhaitez probablement exécuter unzipl' -joption, comme dans:

unzip -j files.zip -d ./output/

Mais vous pourriez être surpris par son comportement:

-j chemins indésirables. La structure du répertoire de l'archive n'est pas recréée; tous les fichiers sont déposés dans le répertoire d'extraction (par défaut, le répertoire actuel).

Si vous extrayez files.zipdans le répertoire de sortie ./outputet que vous obtenez ceci comme résultat:

./output/files/subfolder1/f1
./output/files/subfolder1/f2

alors l' -joption vous donnera ceci (tous les chemins rayés):

./output/f1
./output/f2
Vincenzo Pii
la source