Crea directory se l'archivio zip contiene diversi file


8

Se un archivio contiene diversi file nella directory principale, vorrei creare una directory che prende il nome dal nome del file (senza estensione). Se un archivio contiene solo una directory, mi piacerebbe semplicemente estrarlo. Supponiamo di avere il seguente archivio:

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

Se lo estraggo nella directory corrente mi piacerebbe averlo semplicemente estratto ( unzip withdir.zip):

somedir/alpha
somedir/beta
somedir/gamma

Ora supponi il seguente archivio:

# file: nodir.zip
alpha
beta
gamma

Quando corro unzip nodir.zipfinisco per ingombrare la directory corrente con i tre file:

alpha
beta
gamma

Preferirei correre unzip -d nodir nodir.zip:

nodir/alpha
nodir/beta
nodir/gamma

Se uso nautilus e faccio clic con il tasto destro su "Estrai qui". Si comporta esattamente come dovrebbe. Ma sfortunatamente non ho trovato un'opzione da riga di comando unzipo 7zche produca lo stesso comportamento. Come raggiungerlo? Ci sono altri strumenti che posso usare invece (nessuna GUI)?

Risposte:


7

Vorrei fare qualcosa del genere (sintassi 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
)

Questo è:

  1. crea una directory in qualunque caso
  2. esegui il comando
  3. a seconda di quanti file ha generato il comando:
    • rimuovere quella directory (se non ha creato alcun file)
    • se ha creato solo un file / dir, spostalo di un livello in alto e scarta la nostra directory
    • in caso contrario, prova a rimuovere la stringa casuale dalla fine della nostra directory temporanea.

In questo modo, puoi fare:

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

Presuppone che l'ultimo argomento del comando di estrazione sia il file da estrarre. Presuppone inoltre strumenti GNU per le -vopzioni. Su sistemi non GNU, è possibile rimuoverli ed eventualmente eseguire manualmente la registrazione. mv -Tè anche specifico di GNU e deve forzare il mvtentativo di rinominare solo.


3

Come unzipe 7zentrambi hanno un interruttore per l'uscita a una determinata directory, è possibile creare un semplice script, che i controlli, quanti file sono nella radice dell'archivio e quindi aggiunge l'interruttore, se necessario.

Con 7z questo è più semplice, in quanto ha l' -sltinterruttore, che rende l'output più leggibile dalla macchina. Per ogni file nella zip, l'output conterrà una Path = ...riga. I file nella radice non devono contenere alcun /valore.

Un semplice script che ho scritto per decomprimere i file in questo modo:

#!/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

Modifica: lo script ora funziona anche con zip


Questo script non funziona come previsto. Crea una directory withdirper l'archivio withdir.zipsebbene contenga solo una directory nella radice perché grep -c "Folder = -"restituisce 3.
Marco

ah, la cartella sembra essere diversa per i file zip. Cercherò una soluzione
crater2150

@Marco: ho modificato lo script e testato con i file zip, ora crea la cartella solo quando necessario
crater2150

3

patool gestisce diversi tipi di archivi e crea una sottodirectory nel caso in cui l'archivio contenga più file per evitare di ingombrare la directory di lavoro con i file estratti.

Crea un archivio

patool create archive.zip somedirectory

Estrai archivio

patool extract archive.zip

Per ottenere un elenco dei formati supportati, utilizzare patool formats.


1

È inoltre possibile utilizzare unar , che crea una directory contenente per impostazione predefinita quando sono presenti due o più file di livello superiore:

$ 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

Aggiungi -dper creare sempre una directory contenente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.