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


19

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

Se o último for verdadeiro, como forçar o unzipcomando 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 /tmp/omeka/, (um nível acima e nenhum número de versão incluído na estrutura de diretórios)

/tmp/omeka/(files)

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


ps: Eu estou ciente de que posso extrair e, em seguida, mvos arquivos, mas eu queria ver se havia uma maneira de fazer isso imediatamente a partir do comando de descompactação
cwd

Eu não estou ciente de um. Mas se o nome do arquivo sempre corresponder (além da extensão) ao nome do diretório, é bastante simples criar um script para renomear o diretório extraído.
Mat

3
Entendo o que você está tentando fazer, mas não o recomendaria. Retirar o número da versão das fontes do projeto é uma má idéia; você deve extrair normalmente e usar ln -s se quiser um nome mais curto sem informações de versão. Dessa forma, você sempre sabe qual versão está executando e pode atualizar facilmente para uma nova versão alternando o link.
Burton Samograd

@BurtonSamograd - seria o ideal, mas ainda estou curioso para saber se existe uma maneira eficaz de fazer isso, porque algum software, como o Wordpress, coloca todas as versões em um /wordpress/diretório (sem número de versão) dentro do arquivo zip. Na verdade, é bom unzip, mvmas não ter controle sobre isso e fazê-lo em duas etapas sempre me irritou um pouco. Felizmente Wordpress também vem em um .tar.gzsabor :)
cwd

Tentecd /tmp/omeka && ln -s -T . omeka-1.5.1
James Youngman

Respostas:


4

Use um sistema de arquivos FUSE que permita navegar por arquivos como diretórios, como o AVFS . Use cppara 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 assumimos que existe um único diretório de nível superior no arquivo morto, você pode reduzi-lo para

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

@Giles, você é o especialista que vem e responde a todas as perguntas que ninguém mais pode responder, então acho que essa é realmente a única maneira de fazer isso. Eu esperava que unziptivesse alguma mágica para fazer isso, como especificar os arquivos a serem extraídos */*, que eu pudesse usar sem instalar outro utilitário, mas acho que não. Obrigado. +1
cwd

6

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

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

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

Apenas verifica se existe exatamente um subdiretório e, se houver, move tudo para fora e o exclui.


2

Acabei de me registrar hoje, por isso não posso votar em @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 o @SteveBennet disse: esse script não é robusto, mas funciona nos casos simples.

Espero que seja útil.


1

Necessidade parece patch --strip=n opção

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

Outra solução, aplicabilidade

Na falta disso, existe outra solução, meio hackeada, 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 essa solução funcionar e a solução da @ Gilles estiver disponível, a última também funcionará. No entanto, esta solução não requer disponibilidade de um sistema de arquivos FUSE.

Como fazer isso

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

unziptentará descompactar para o omeka-1.5.1qual é realmente um link simbólico para conter dir. Como resultado, os arquivos serão omekadirecionados diretamente.

Variantes possíveis

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

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

Conclusão

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


Ótima solução se você conhece o caminho!
grepsedawk

O caminho pode ser investigado listando o conteúdo zip primeiro, por exemplo, com unzip -l. Isso pode até ser automatizado usando um script que descobre parte do caminho comum.
Stéphane Gourichon

Ah, totalmente, é apenas uma tonelada mais fácil se você conhece o caminho. Joguei com descompactar -l por um tempo, mas foi um pouco mais grep / sed / awk do que pretendia, então desisti.
grepsedawk

zipinfo -1pode ser um bom começo. Qual é o seu caso de uso?
Stéphane Gourichon 03/07

github.com/grepsedawk/wow-config/blob/… nesse caso, eu sei o diretório :)
grepsedawk

1

Provavelmente você deseja executar unzipcom a -jopção, como em:

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

Mas você pode se surpreender com o seu comportamento:

-j caminhos indesejados. A estrutura de diretórios do arquivo morto não é recriada; todos os arquivos são depositados no diretório de extração (por padrão, o atual).

Se você extrair files.zipno diretório de saída ./outpute obter isso como resultado:

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

então a -jopção fornecerá a você (todos os caminhos divididos):

./output/f1
./output/f2
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.