Descarga y descomprime ZIP, tar.gz y gzip con cURL
Conecta cURL mediante una tubería a tar o gzip
para descomprimir una descarga a medida que llega. Para los archivos ZIP, descarga primero a un
archivo temporal y luego ejecuta unzip. Los siguientes ejemplos comprueban
tanto la descarga como la extracción y no permiten reutilizar un directorio de salida existente.
Comandos básicos de cURL para descargar
Usa Bash en Linux, cURL, GNU tar, GNU gzip, Info-ZIP UnZip y las utilidades estándar
mkdir, mktemp y rm.
Los comandos se probaron en Ubuntu 24.04 con Bash 5.2, cURL 8.5.0, GNU tar 1.35, gzip 1.12 y
UnZip 6.00. No son comandos de PowerShell ni comandos genéricos de sh.
Elige el bloque correspondiente a tu formato y sustituye su URL https://example.com/…
por una URL de descarga de confianza. Ejecuta el bloque completo, incluidos los paréntesis, en Bash
desde un directorio que te pertenezca y en el que puedas escribir. Cada bloque es independiente.
También puedes guardar uno como extract.sh y ejecutar bash extract.sh.
Las opciones de cURL que se usan aquí son:
-f: Devuelve un error ante fallos HTTP como 404, sin enviar la página de error al extractor.-sS: Oculta el indicador de progreso, pero sigue mostrando los errores.-L: Sigue las redirecciones.-o: Escribe la descarga en el archivo especificado en lugar de la salida estándar.
El directorio de salida no debe existir, aunque esté vacío. mkdir
lo reserva antes de que comience cualquier descarga; no cambies ese comando por
mkdir -p. El manejador de limpieza se instala solo después de que el directorio
se haya creado correctamente, por lo que repetir un comando deja intacto el resultado anterior.
umask 077 hace que los directorios de trabajo recién creados sean privados para
tu usuario, aunque las entradas del archivo contenedor pueden incluir sus propios modos de permisos.
Manejo de distintos formatos de archivo contenedor
Archivos ZIP (.zip)
Info-ZIP UnZip 6.0 no lee un archivo contenedor desde stdin. Su opción -p
envía los archivos extraídos a stdout; no acepta un ZIP mediante una tubería como entrada.
El manual de UnZip documenta esta limitación. Usa un archivo normal
descargado para que el extractor pueda desplazarse por él.
(
umask 077
dest='./zip-output'
mkdir -- "$dest" || exit
trap 'rm -rf -- "$dest"' EXIT
work=$(mktemp -d) || exit
trap 'rm -rf -- "$work" "$dest"' EXIT
curl -fsSL 'https://example.com/archive.zip' -o "$work/archive.zip" || exit
unzip -q "$work/archive.zip" -d "$dest" </dev/null || exit
rm -rf -- "$work" || exit
trap - EXIT
printf 'Extracted to %s\n' "$dest"
)
Si la operación finaliza correctamente, los archivos quedan en ./zip-output/,
con la estructura de directorios del archivo contenedor intacta. mktemp -d
crea un directorio temporal único en $TMPDIR o en
/tmp si la variable no está definida. Solo se elimina esa copia privada de
archive.zip. Nunca se utiliza un archivo llamado temp.zip
que esté en tu directorio actual. Este ejemplo es para archivos ZIP sin cifrar; cerrar stdin evita
que una solicitud de entrada interactiva bloquee el comando.
Archivos tar comprimidos con gzip (.tar.gz o .tgz)
Un archivo tar comprimido con gzip se puede transmitir directamente a GNU tar:
(
set -o pipefail
umask 077
dest='./tar-output'
mkdir -- "$dest" || exit
trap 'rm -rf -- "$dest"' EXIT
curl -fsSL 'https://example.com/archive.tar.gz' | tar -xzf - -C "$dest" || exit
trap - EXIT
printf 'Extracted to %s\n' "$dest"
)
Aquí, -x extrae, -z descomprime gzip,
-f - lee el archivo contenedor desde stdin y -C
elige el directorio de extracción. Los archivos quedan en ./tar-output/;
no se guarda ningún archivo comprimido. Si el archivo contenedor incluye un directorio de nivel
superior, ese directorio permanece dentro de tar-output.
La opción pipefail de Bash hace que el pipeline
falle cuando falla cURL o tar. Sin ella, un extractor que finalice correctamente puede ocultar una
transferencia fallida, incluso una que notifique un error después de entregar bytes utilizables del
archivo contenedor. || exit devuelve el estado de fallo del subshell y activa
la limpieza. Los paréntesis impiden que estos ajustes del shell y las llamadas a
exit afecten a tu sesión interactiva.
Archivos gzip (.gz)
Gzip por sí solo comprime un flujo de bytes; no proporciona un árbol de directorios. Elige
explícitamente el nombre del archivo de salida con gzip -dc y una redirección:
(
set -o pipefail
umask 077
dest='./gzip-output'
mkdir -- "$dest" || exit
trap 'rm -rf -- "$dest"' EXIT
curl -fsSL 'https://example.com/file.gz' | gzip -dc > "$dest/payload" || exit
trap - EXIT
printf 'Decompressed to %s/payload\n' "$dest"
)
-d descomprime y -c escribe en stdout.
El resultado es ./gzip-output/payload, incluso cuando el archivo original está vacío o
contiene datos binarios. El directorio que lo contiene evita que la redirección trunque un resultado
anterior. Si un archivo llamado .gz contiene en realidad un archivo tar,
usa el ejemplo de tar con esa URL para extraer su contenido.
Consideraciones de seguridad
Usa estos comandos con archivos contenedores de una fuente en la que confíes, como tu usuario
habitual. El directorio nuevo protege los resultados existentes frente a una reutilización
accidental; no es un entorno aislado. Las rutas, los enlaces y los permisos del archivo
contenedor, las vulnerabilidades del extractor y un tamaño excesivo tras la descompresión siguen
siendo importantes. Las recomendaciones de seguridad de GNU tar
explican los riesgos de extraer archivos contenedores que no sean de confianza.
--strip-components cambia la estructura de las rutas; no hace que un archivo contenedor
arbitrario sea seguro.
La transmisión empieza a escribir archivos antes de que termine la transferencia. Espera a que el estado de salida sea cero y aparezca el mensaje de éxito antes de usarlos. Si hay un error de descarga o extracción, el manejador elimina el directorio de salida recién creado. Una terminación forzada o un error de permisos durante la limpieza pueden dejar archivos parciales; inspecciona ese directorio antes de elegir un nuevo destino para reintentar la operación.
Problemas comunes y consejos para solucionarlos
- El destino ya existe: Elige un nombre nuevo para
dest. El comando falla deliberadamente antes de descargar, conservando el directorio, archivo o enlace simbólico existente. - cURL notifica un error HTTP o de conexión: Comprueba la URL de descarga y los requisitos de acceso. Una página web que devuelve HTTP 200 sigue sin ser un archivo contenedor; el extractor también debe aceptar el contenido descargado.
- El extractor notifica un EOF inesperado, un error de suma de comprobación o un formato no válido:
Considera que el resultado es fallido. Confirma el formato y obtén una copia completa del editor.
Un sufijo
.gzpor sí solo no indica si el contenido es un archivo tar. - Una transferencia se interrumpe repetidamente: Vuelve a ejecutar el bloque completo después de resolver la causa. No te limites a añadir opciones de reintento a una tubería: cURL no puede retirar los bytes ya enviados al siguiente comando. Su documentación sobre reintentos advierte que la salida redirigida puede recibir datos duplicados.
- La extracción se queda sin espacio: Reserva espacio para los archivos descomprimidos. El ejemplo de ZIP también necesita espacio para el archivo contenedor descargado en el directorio temporal.
Elige cuándo guardar el archivo contenedor
Transmitir tar.gz y gzip sin guardarlos ahorra el espacio en disco de la descarga comprimida. Si necesitas comparar la suma de comprobación del editor o verificar una firma antes de extraer, descarga primero a un directorio de trabajo nuevo y verifica ese archivo. Que un extractor acepte el archivo contenedor demuestra que pudo leerlo; no demuestra quién lo publicó.
