Como redirecionar a saída do wget como entrada para descompactar?


131

Eu tenho que baixar um arquivo deste link . O download do arquivo é um arquivo zip que precisarei descompactar na pasta atual.

Normalmente, eu deveria baixá-lo primeiro e depois executar o comando descompactar.

$ wget http://www.vim.org/scripts/download_script.php?src_id=11834 -O temp.zip
$ unzip temp.zip

Mas dessa forma, preciso executar dois comandos, aguardar a conclusão do primeiro para executar o próximo, além disso, preciso saber o nome do arquivo temp.zippara o qual dar unzip.

É possível redirecionar a saída de wgetpara unzip? Algo como

$ unzip < `wget http://www.vim.org/scripts/download_script.php?src_id=11834`

Mas não deu certo.

bash :: wget http://www.vim.org/scripts/download_script.php?src_id=11834 -O temp.zipredirecionamento ambíguo

Além disso, wgetfoi executado duas vezes e baixou o arquivo duas vezes.


No último exemplo, o wget provavelmente foi executado duas vezes porque o? é um caractere especial no shell. Colocar o URL em "" s deve ajudar.
p-static

Este tópico parece ter uma solução. Ainda não tentei. serverfault.com/questions/26474/…

Respostas:


96

Você precisa baixar seus arquivos para um arquivo temporário, porque (citando a página de manual descompactar):

Os arquivos lidos a partir da entrada padrão ainda não são suportados, exceto com o funzip (e somente o primeiro membro do arquivo pode ser extraído).

Basta reunir os comandos:

wget http://www.vim.org/scripts/download_script.php?src_id=11834 -O temp.zip; unzip temp.zip; rm temp.zip

Mas, para torná-lo mais flexível, você provavelmente deve colocá-lo em um script para salvar algumas digitações e, para garantir que não substitua acidentalmente algo, use o mktempcomando para criar um nome de arquivo seguro para o seu arquivo temporário:

#!/bin/bash
TMPFILE=`mktemp`
PWD=`pwd`
wget "$1" -O $TMPFILE
unzip -d $PWD $TMPFILE
rm $TMPFILE

É wget file.zip && unzip file.zipigual wget file.zip; unzip file.zipou prefere um ao outro? Obrigado :)
jaggedsoft

7
O @NextLocal wget && unzipserá descompactado apenas se o wget for bem-sucedido. wget ; unzipexecutará o descompactação de qualquer maneira, possivelmente apontando para um arquivo inexistente.
temoto 7/02

funzip foi a resposta que eu estava procurando. Os pacotes Terraform (por algum motivo) são binários como um único arquivo em um arquivo zip, então isso foi perfeito para mim.
Asfand Qazi

75

Esta é uma resposta da minha resposta a uma pergunta semelhante:

O formato do arquivo ZIP inclui um diretório (índice) no final do arquivo morto. Esse diretório diz onde, dentro do arquivo, cada arquivo está localizado e, portanto, permite acesso rápido e aleatório, sem a leitura de todo o arquivo.

Isso parece representar um problema ao tentar ler um arquivo ZIP por meio de um canal, pois o índice não é acessado até o final e, portanto, os membros individuais não podem ser extraídos corretamente até depois que o arquivo foi totalmente lido e não está mais disponível . Como tal, não surpreende que a maioria dos descompressores ZIP simplesmente falhe quando o arquivo é fornecido através de um tubo.

O diretório no final do arquivo morto não é o único local em que as meta informações do arquivo são armazenadas no arquivo morto. Além disso, entradas individuais também incluem essas informações em um cabeçalho de arquivo local, para fins de redundância.

Embora nem todos os descompactadores ZIP usem cabeçalhos de arquivos locais quando o índice estiver indisponível, os front-ends tar e cpio para libarchive (também conhecidos como bsdtar e bsdcpio) podem e o fazem ao ler através de um canal , o que significa que o seguinte é possível:

wget -qO- http://example.org/file.zip | bsdtar -xvf-

1
Isto e excelente! Eu observaria que o tar me dá alguns avisos sobre os dados não compactados serem do tamanho errado (esperado 0), mas os arquivos parecem não estar danificados. Supondo que isso se deva à falta do índice.
Wyatt8740

1
Eu tenho um .ziparquivo aqui que contém arquivos com permissões executáveis. Quando eu baixo e entro bsdtar, os bits de exec são jogados fora. Quando eu faço o download em disco e extraio com bsdtarou unzipentão, os bits exec são respeitados.
Golar Ramblar

//, @ GolarRamblar, você já descobriu por que?
Nathan Basanese

1
@ NathanBasanese: aqui está a resposta. Resumindo: um arquivo ZIP possui dois locais onde armazena essas informações, que podem ser inconsistentes e, dependendo da bsdtarabertura do arquivo, é possível procurar ou não o uso de um ou outro local.
Golar Ramblar

20

Se você tiver o JDK instalado, poderá usar jar:

wget -qO- http://example.org/file.zip | jar xvf /dev/stdin

3
Acabei de descobrir que jarnão preserva as permissões de arquivo. Bom truque caso contrário.
phunehehe

7
Você não precisa dar um param arquivo, basta usar| jar xv
cricket_007

15

Eu acho que você nem quer incomodar a saída do wget da tubulação para descompactar.

No artigo "ZIP (formato de arquivo)" da wikipedia :

Um arquivo ZIP é identificado pela presença de um diretório central localizado no final do arquivo.

O wget precisa concluir completamente o download antes que o descompactamento possa executar qualquer trabalho, para que sejam executados seqüencialmente, não entrelaçados como se poderia pensar.


10

A sintaxe adequada seria:

$ unzip <(curl -sL https://www.winpcap.org/archive/1.0-docs.zip)

mas não funcionará, devido ao erro ( Info-ZIP no Debian ):

lseek(3, 0, SEEK_SET)                   = -1 ESPIPE (Illegal seek)

Archive:  /dev/fd/63
  End-of-central-directory signature not found.  Either this file is not
  a zipfile, or it constitutes one disk of a multi-part archive.  In the
  latter case the central directory and zipfile comment will be found on
  the last disk(s) of this archive.
unzip:  cannot find zipfile directory in one of /dev/fd/63 or
        /dev/fd/63.zip, and cannot find /dev/fd/63.ZIP, period.

ou no BSD / OS X:

Trying to read large file (> 2 GiB) without large file support

Isso ocorre porque as ferramentas zip padrão usam principalmente a lseekfunção para definir o deslocamento do arquivo no final para ler o final do registro do diretório central . Ele está localizado no final da estrutura do arquivo morto e é necessário ler a lista dos arquivos (consulte: Estrutura de formato de arquivo zip ). Portanto, o arquivo não pode ser FIFO, canal, dispositivo terminal ou qualquer outra dinâmica, porque o objeto de entrada não pode ser posicionado pela lseekfunção.

Então você tem as seguintes soluções alternativas:

  • use diferentes tipos de compactação (por exemplo tar.gz),
  • você tem que usar dois comandos separados,
  • use ferramentas alternativas (como sugerido em outras respostas),
  • crie um alias ou função para usar vários comandos.

Eu acho que ainda poderia ser um FIFO. Você apenas precisaria continuar lendo do FIFO até o EOF (efetivamente armazenando em buffer todo o FIFO na memória ou em um arquivo temporário). Totalmente possível para facilitar a criação de scripts, mas não é muito útil.
Evan Carroll

8

Repost da minha resposta :

O BusyBox unzippode pegar o stdin e extrair todos os arquivos.

wget -qO- http://downloads.wordpress.org/plugin/akismet.2.5.3.zip | busybox unzip -

O ponto a seguir unzipé usar stdin como entrada.

Você também pode,

cat file.zip | busybox unzip -

Mas isso é apenas redundante unzip file.zip.

Se sua distribuição usar o BusyBox por padrão (por exemplo, Alpine), basta executar unzip -.


Truque muito útil, obrigado!
Brice

-1

Isso funciona muito bem para mim:

tar xvf <(curl -sL http://www.vim.org/scripts/download_script.php?src_id=11834)

jar xvf <(curl -sL http://www.vim.org/scripts/download_script.php?src_id=11834)

wget -qO- http://www.vim.org/scripts/download_script.php?src_id=11834 | tar xvf -

wget -qO- http://www.vim.org/scripts/download_script.php?src_id=11834 | jar xvf -
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.