Como posso forçar o unzip / zip a não criar um subdiretório ao extraí-lo?

19

Dependendo de como um arquivo zip é criado, às vezes ele extrai todos os arquivos diretamente e, às vezes, extrai os arquivos em um subdiretório.

Se o último for verdadeiro, como posso forçar o comando unzip a "ignorar" esse diretório de primeiro nível?

Exemplo:

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

O que estou recebendo é /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/

O que eu quero é dos arquivos extraídos para /tmp/omeka/ , (um nível acima e nenhum número de versão incluído na estrutura do diretório)

/tmp/omeka/(files)

Eu sei que posso usar a opção -j para "caminhos de lixo", mas quero manter a estrutura do subdiretório, mas não a estrutura de diretórios de nível superior. Como posso fazer isso?

    
por cwd 08.05.2012 / 20:51

6 respostas

4

Use um sistema de arquivos FUSE que permita navegar em arquivos como diretórios, como AVFS . Use cp para extrair os arquivos para o diretório de sua escolha.

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

Como estamos assumindo que há um único diretório de nível superior no arquivo, você pode encurtar isso para

cp -Rp ~/.avfs/tmp/omeka-1.5.1.zip\#/* omeka
    
por 09.05.2012 / 00:57
6

Se o seu arquivo zip não contiver nenhuma estrutura de diretórios ou você não precisar preservá-lo, você pode usar isto:

cd /tmp
wget http://omeka.org/files/omeka-1.5.1.zip
unzip -j omeka-1.5.1.zip -d omeka
cd omeka
ll
    
por 24.07.2013 / 18:24
3

Este script não é robusto, mas funciona nos casos 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

Ele apenas verifica se há exatamente um subdiretório e, em caso afirmativo, move tudo para fora e, em seguida, exclui-o.

    
por 25.02.2014 / 13:30
2

Acabei de me inscrever hoje, por isso não posso contestar a resposta do @SteveBennet e não posso adicionar um comentário lá.

Com base em sua resposta, criei uma função recursiva como esta:

...

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"

Assim como @SteveBennet disse: este script não é robusto, mas funciona nos casos simples.

Espero que seja útil.

    
por 14.03.2014 / 16:22
0

A necessidade parece com patch --strip=n option

Seria desejável ter uma opção como patch --strip=number (ou -pnumber ) que corta number componentes do caminho no início (ref. Comparando e mesclando arquivos: patch diretórios ).

Outra solução, aplicabilidade

Na falta disso, há outra solução, meio que trabalhosa, mas funciona. No meu caso, eu queria sobrescrever um diretório cheio de arquivos existentes com o conteúdo de um zip, sem extrair o zip completo primeiro.

Quando esta solução funciona e a solução @ Gilles está disponível, a segunda também funciona. No entanto, esta solução não requer a disponibilidade de um sistema de arquivos FUSE.

Como fazer

Supondo que você conheça o diretório extra, no seu caso omeka-1.5.1 , você pode fazer isso:

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

unzip tentará descompactar para omeka-1.5.1 , que é na verdade um link simbólico para conter dir. Como resultado, os arquivos serão carregados em omeka diretamente.

Variantes possíveis

Você pode imaginar variantes para redirecionar uma ou mais partes de uma hierarquia de defuntos.

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

Conclusão

Esta solução é um tanto específica, mas tem seus casos de uso e eu acabei por usá-la.

    
por 26.12.2016 / 22:02
0

O mais provável é que você queira executar unzip com a opção -j , como em:

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

Mas você pode se surpreender com o comportamento dele:

-j junk paths. The archive's directory structure is not recreated; all files are deposited in the extraction directory (by default, the current one).

Se você extrair files.zip no diretório de saída ./output e obter isso como resultado:

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

então a opção -j lhe dará isto (todos os caminhos listados):

./output/f1
./output/f2
    
por 24.04.2017 / 18:44

Tags