¿Cómo redirigir la salida de wget como entrada para descomprimir?

131

Tengo que descargar un archivo desde este enlace . La descarga del archivo es un archivo zip que tendré que descomprimir en la carpeta actual.

Normalmente, lo descargaría primero, luego ejecutaría el comando descomprimir.

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

Pero de esta manera, necesito ejecutar dos comandos, esperar a que se complete el primero para ejecutar el siguiente, también, debo saber el nombre del archivo temp.zippara dárselo unzip.

¿Es posible redirigir la salida de wgetto unzip? Algo como

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

Pero no funcionó.

bash: wget http://www.vim.org/scripts/download_script.php?src_id=11834 -O temp.zipredirección ambigua

Además, wgetse ejecutó dos veces y descargó el archivo dos veces.

Andrew-Dufresne
fuente
En el último ejemplo, wget probablemente se ejecutó dos veces porque el? Es un personaje especial en el shell. Poner la URL en "" s debería ayudar.
p-static
Este hilo parece tener una solución. Aunque no lo he probado. serverfault.com/questions/26474/…

Respuestas:

96

Debe descargar sus archivos a un archivo temporal porque (citando la página del manual de descompresión):

Los archivos leídos desde la entrada estándar aún no son compatibles, excepto con funzip (y luego solo se puede extraer el primer miembro del archivo).

Solo reúna los comandos:

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

Pero para que sea más flexible, probablemente deberías ponerlo en un script para que guardes algo de escritura y para asegurarte de no sobrescribir accidentalmente algo, puedes usar el mktempcomando para crear un nombre de archivo seguro para tu archivo temporal:

#!/bin/bash
TMPFILE=`mktemp`
PWD=`pwd`
wget "$1" -O $TMPFILE
unzip -d $PWD $TMPFILE
rm $TMPFILE
tante
fuente
¿Es wget file.zip && unzip file.zipigual wget file.zip; unzip file.zipo se prefiere uno sobre el otro? Gracias :)
jaggedsoft
77
@NextLocal wget && unzipse ejecutará descomprimir solo si wget tuvo éxito. wget ; unzipse ejecutará descomprimir de todos modos, posiblemente apuntando a un archivo inexistente.
temoto
Funzip fue la respuesta que estaba buscando. Terraform (por alguna razón) empaqueta es binario como un solo archivo en un archivo zip, así que fue perfecto para mí.
Asfand Qazi
75

Esta es una nueva publicación de mi respuesta a una pregunta similar:

El formato del archivo ZIP incluye un directorio (índice) al final del archivo. Este directorio dice dónde, dentro del archivo, se encuentra cada archivo y, por lo tanto, permite un acceso rápido y aleatorio, sin leer todo el archivo.

Esto parecería plantear un problema al intentar leer un archivo ZIP a través de una tubería, ya que no se accede al índice hasta el final y, por lo tanto, los miembros individuales no se pueden extraer correctamente hasta que el archivo se haya leído por completo y ya no esté disponible . Como tal, no parece sorprendente que la mayoría de los descompresores ZIP simplemente fallen cuando el archivo se suministra a través de una tubería.

El directorio al final del archivo no es la única ubicación donde se almacena la información meta del archivo en el archivo. Además, las entradas individuales también incluyen esta información en un encabezado de archivo local, con fines de redundancia.

Aunque no todos los descompresores ZIP usarán encabezados de archivos locales cuando el índice no esté disponible, los front-end tar y cpio para libarchive (también conocido como bsdtar y bsdcpio) pueden y lo harán al leer a través de una tubería, lo que significa que lo siguiente es posible:

wget -qO- http://example.org/file.zip | bsdtar -xvf-
ruario
fuente
1
¡Esto es excelente! Me gustaría señalar que tar me da algunas advertencias sobre los datos sin comprimir que tienen el tamaño incorrecto (esperado 0), pero los archivos en sí mismos parecen no estar dañados. Adivinar esto se debe a la falta del índice.
Wyatt8740
1
Tengo un .ziparchivo aquí que contiene archivos con permisos ejecutables. Cuando descargo y canalizo bsdtar, los bits de ejecución se descartan. Cuando descargo al disco y extraigo con bsdtaro unzipluego, se respetan los bits de ejecución.
Golar Ramblar
//, @GolarRamblar, ¿alguna vez descubriste por qué?
Nathan Basanese
1
@NathanBasanese: aquí está la respuesta. En resumen: un archivo ZIP tiene dos lugares donde almacena dicha información, que puede ser inconsistente, y dependiendo de si el archivo se bsdtarabre o no se puede buscar, se usa uno u otro lugar.
Golar Ramblar
20

Si tiene instalado el JDK, puede usar jar:

wget -qO- http://example.org/file.zip | jar xvf /dev/stdin
Rory Hunter
fuente
3
Acabo de encontrar que jarno conserva los permisos de archivo. Buen truco de lo contrario.
phunehehe
77
No necesita dar un | jar xv
parámetro de
15

No creo que quiera molestarse en descomprimir la salida de wget de tubería.

Del artículo "ZIP (formato de archivo)" de Wikipedia:

Un archivo ZIP se identifica por la presencia de un directorio central ubicado al final del archivo.

wget tiene que finalizar la descarga por completo antes de que descomprimir pueda hacer cualquier trabajo, por lo que se ejecutan secuencialmente, no entrelazados como se podría pensar.

Bruce Ediger
fuente
10

La sintaxis adecuada sería:

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

pero no funcionará debido al error ( Info-ZIP en 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 en BSD / OS X:

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

Esto se debe a que las herramientas zip estándar utilizan principalmente la lseekfunción para establecer el desplazamiento del archivo al final para leer el final del registro del directorio central . Se encuentra al final de la estructura de archivo y es necesario leer la lista de archivos (ver: Estructura de formato de archivo Zip ). Por lo tanto, el archivo no puede ser FIFO, tubería, dispositivo terminal o cualquier otra dinámica, porque la función no puede colocar el objeto de entrada lseek.

Entonces tiene las siguientes soluciones:

  • utilizar diferentes tipos de compresión (p tar.gz. ej. )
  • tienes que usar dos comandos separados,
  • usar herramientas alternativas (como se sugiere en otras respuestas),
  • cree un alias o función para usar múltiples comandos.
kenorb
fuente
Creo que todavía podría ser un FIFO. Simplemente tendría que seguir leyendo desde el FIFO hasta el EOF (almacenando de manera efectiva el FIFO completo en la memoria o en un archivo temporal). Totalmente factible para facilitar la creación del script, pero no es muy útil.
Evan Carroll
8

Publicación de mi respuesta :

BusyBox unzippuede tomar stdin y extraer todos los archivos.

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

El guión después unzipes usar stdin como entrada.

Tu puedes incluso,

cat file.zip | busybox unzip -

Pero eso es redundante unzip file.zip.

Si su distribución usa BusyBox de forma predeterminada (por ejemplo, Alpine), simplemente ejecute unzip -.

Saftever
fuente
Truco muy útil, gracias!
Brice
-1

Esto me funciona bastante bien:

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 -
Maksim Kostromin
fuente