Crie o diretório se o arquivo zip contiver vários arquivos

8

Se um arquivo contiver vários arquivos no diretório raiz, eu gostaria de criar um diretório nomeado após o nome do arquivo (sem extensão). Se um arquivo contém apenas um diretório, então eu gostaria de simplesmente extraí-lo. Suponho que tenho o seguinte arquivo:

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

Se eu extraí-lo no diretório atual eu gostaria de tê-lo simplesmente extraído ( unzip withdir.zip ):

somedir/alpha
somedir/beta
somedir/gamma

Agora assuma o seguinte arquivo:

# file: nodir.zip
alpha
beta
gamma

Quando eu corro unzip nodir.zip acabo bagunçando o diretório atual com os três arquivos:

alpha
beta
gamma

Eu prefiro executar unzip -d nodir nodir.zip :

nodir/alpha
nodir/beta
nodir/gamma

Se eu usar nautilus e clicar com o botão direito em "Extrair aqui". Ele se comporta exatamente como devemos. Mas infelizmente não encontrei uma linha de comando para unzip ou 7z que produz o mesmo comportamento. Como conseguir isso? Existem outras ferramentas que eu posso usar? (sem GUI)?

    
por Marco 07.02.2013 / 11:29

4 respostas

7

Eu faria algo assim (sintaxe 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
)

Isto é:

  1. crie um diretório em qualquer pasta
  2. execute o comando
  3. dependendo de quantos arquivos o comando gerou:
    • remova esse diretório (se ele não criou nenhum arquivo)
    • se tiver criado apenas um arquivo / dir, mova-o um nível para cima e descarte nosso diretório
    • caso contrário, tente remover a string aleatória do final do nosso diretório temporário.

Dessa forma, você pode fazer:

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

Ele assume que o último argumento para o comando de extração é o arquivo a ser extraído. Ele também assume ferramentas GNU para as opções -v . Em sistemas não-GNU, você pode removê-los e possivelmente fazer o log manualmente. mv -T também é específico do GNU e forçará mv a tentar renomear apenas.

    
por 07.02.2013 / 12:50
3

Como unzip e 7z têm uma opção de saída para um determinado diretório, você pode criar um script simples, que verifica quantos arquivos estão na raiz do arquivamento e, em seguida, adiciona a opção, se necessário.

Com o 7z isso é mais fácil, pois tem a opção -slt , o que torna a saída mais legível por máquina. Para cada arquivo no zip, a saída conterá uma linha Path = ... . Arquivos na raiz não devem conter / no valor.

Um script simples que escrevi para descompactar arquivos dessa maneira:

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

Editar: o script agora também funciona com o zip

    
por 07.02.2013 / 12:15
3

O patool lida com diferentes tipos de arquivos e cria um subdiretório para o caso de o arquivo conter vários os arquivos extraídos.

Criar arquivo

patool create archive.zip somedirectory

Extrair arquivo

patool extract archive.zip

Para obter uma lista dos formatos suportados, use patool formats .

    
por 13.04.2013 / 19:44
1

Você também pode usar o unar , que cria um diretório contendo por padrão quando há dois ou mais arquivos de nível superior:

$ 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

Adicione -d para sempre criar um diretório contendo.

    
por 29.04.2014 / 10:01

Tags