Come reindirizzare l'output di wget come input per decomprimerlo?


131

Devo scaricare un file da questo link . Il download del file è un file zip che dovrò decomprimere nella cartella corrente.

Normalmente, lo scaricarei prima, quindi eseguo il comando unzip.

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

Ma in questo modo, devo eseguire due comandi, attendere il completamento del primo per eseguire il successivo, inoltre, devo conoscere il nome del file temp.zipa cui dare unzip.

È possibile reindirizzare l'output di wgeta unzip? Qualcosa di simile a

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

Ma non ha funzionato.

bash:: wget http://www.vim.org/scripts/download_script.php?src_id=11834 -O temp.zipreindirizzamento ambiguo

Inoltre, è wgetstato eseguito due volte e scaricato il file due volte.


Nell'ultimo esempio, wget probabilmente è stato eseguito due volte perché il? è un personaggio speciale nella shell. Mettere l'URL in "" s dovrebbe aiutare.
p-static

Questa discussione sembra avere una soluzione. Non l'ho provato da solo. serverfault.com/questions/26474/…

Risposte:


96

Devi scaricare i tuoi file in un file temporaneo, perché (citando la pagina man di decompressione):

Gli archivi letti dallo standard input non sono ancora supportati, tranne con funzip (e quindi solo il primo membro dell'archivio può essere estratto).

Basta unire i comandi:

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

Ma per renderlo più flessibile dovresti probabilmente inserirlo in uno script in modo da salvare un po 'di digitazione e per assicurarti di non sovrascrivere accidentalmente qualcosa, potresti usare il mktempcomando per creare un nome file sicuro per il tuo file temporaneo:

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

È wget file.zip && unzip file.zipuguale wget file.zip; unzip file.zipo preferito l'uno all'altro? Grazie :)
jaggedsoft il

7
@NextLocal wget && unzipeseguirà la decompressione solo se wget è riuscito. wget ; unzipverrà eseguito decomprimere comunque, eventualmente indicando un file inesistente.
temoto,

funzip era la risposta che stavo cercando. I pacchetti Terraform (per qualche ragione) sono binari come un singolo file in un archivio zip, quindi questo è stato perfetto per me.
Asfand Qazi

75

Questo è un ripubblicare della mia risposta a una domanda simile:

Il formato del file ZIP include una directory (indice) alla fine dell'archivio. Questa directory indica dove si trova ogni file all'interno dell'archivio e consente quindi un accesso rapido e casuale, senza leggere l'intero archivio.

Ciò sembra rappresentare un problema quando si tenta di leggere un archivio ZIP attraverso una pipe, in quanto l'indice non è accessibile fino alla fine e quindi i singoli membri non possono essere estratti correttamente fino a quando il file non è stato letto interamente e non è più disponibile . Pertanto, non sorprende che la maggior parte dei decompressori ZIP non riesca semplicemente quando l'archivio viene fornito attraverso una pipe.

La directory alla fine dell'archivio non è l' unica posizione in cui sono archiviate le meta informazioni sul file. Inoltre, le singole voci includono anche queste informazioni in un'intestazione di file locale, a fini di ridondanza.

Sebbene non tutti i decompressori ZIP utilizzeranno le intestazioni di file locali quando l'indice non è disponibile, i front-end tar e cpio in libarchive (aka bsdtar e bsdcpio) possono e lo faranno quando leggono una pipe, il che significa che è possibile quanto segue:

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

1
Questo è eccellente! Vorrei notare che tar mi dà alcuni avvertimenti sul fatto che i dati non compressi abbiano dimensioni errate (previsto 0), ma i file stessi sembrano non essere danneggiati. Indovinare questo è dovuto alla mancanza dell'indice.
Wyatt8740,

1
Ho un .zipfile qui che contiene file con permessi eseguibili. Quando scarico e eseguo il pipe bsdtar, i bit di exec vengono eliminati. Quando scarico su disco ed estraggo con bsdtaro unzippoi, i bit exec sono onorati.
Golar Ramblar,

//, @GolarRamblar, non hai mai scoperto il perché?
Nathan Basanese,

1
@NathanBasanese: ecco la risposta. In breve: un archivio ZIP ha due posizioni in cui memorizza tali informazioni, che possono essere incoerenti e, a seconda che il file si bsdtarapra sia ricercabile o meno, utilizza l'una o l'altra posizione.
Golar Ramblar,

20

Se hai installato JDK, puoi utilizzare jar:

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

3
Ho appena scoperto che jarnon conserva le autorizzazioni per i file. Bel trucco altrimenti.
phunehehe,

7
Non è necessario fornire un file param, basta usare| jar xv
cricket_007 il

15

Non penso nemmeno che tu voglia disturbare il piping dell'output di wget in unzip.

Dall'articolo "ZIP (formato file)" di wikipedia :

Un file ZIP è identificato dalla presenza di una directory centrale situata alla fine del file.

wget deve completare completamente il download prima che unzip possa fare qualsiasi lavoro, quindi vengono eseguiti in sequenza, non intrecciati come si potrebbe pensare.


10

La sintassi corretta sarebbe:

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

ma non funzionerà, a causa dell'errore ( Info-ZIP su 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.

o su BSD / OS X:

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

Questo perché gli strumenti zip standard utilizzano principalmente la lseekfunzione per impostare l'offset del file alla fine per leggere la sua fine del record della directory centrale . Si trova alla fine della struttura dell'archivio ed è necessario per leggere l'elenco dei file (vedere: Struttura del formato di file zip ). Pertanto il file non può essere FIFO, pipe, dispositivo terminale o qualsiasi altra dinamica, poiché l'oggetto di input non può essere posizionato dalla lseekfunzione.

Quindi hai le seguenti soluzioni alternative:

  • utilizzare diversi tipi di compressione (ad es. tar.gz),
  • devi usare due comandi separati,
  • utilizzare strumenti alternativi (come suggerito in altre risposte),
  • creare un alias o una funzione per utilizzare più comandi.

Penso che potrebbe essere ancora un FIFO. Dovresti solo continuare a leggere da FIFO fino a EOF (bufferizzare efficacemente l'intero FIFO in memoria o in un file temporaneo). Totalmente fattibile per facilitare la creazione di script, ma non molto utile.
Evan Carroll,

8

Repost della mia risposta :

BusyBox unzippuò prendere stdin ed estrarre tutti i file.

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

Il trattino dopo unzipè usare stdin come input.

Puoi persino

cat file.zip | busybox unzip -

Ma questo è solo ridondante unzip file.zip.

Se la tua distribuzione utilizza BusyBox per impostazione predefinita (ad es. Alpine), esegui semplicemente unzip -.


Trucco molto utile, grazie!
Brice,

-1

Questo funziona abbastanza bene per me:

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 -
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.