Tomando el " solo Bash y nada más " estrictamente, aquí hay una adaptación de respuestas anteriores ( @ Chris's , @ 131's ) que no llama a ninguna utilidad externa (ni siquiera estándar) pero también funciona con archivos binarios:
#!/bin/bash
download() {
read proto server path <<< "${1//"/"/ }"
DOC=/${path// //}
HOST=${server//:*}
PORT=${server//*:}
[[ x"${HOST}" == x"${PORT}" ]] && PORT=80
exec 3<>/dev/tcp/${HOST}/$PORT
# send request
echo -en "GET ${DOC} HTTP/1.0\r\nHost: ${HOST}\r\n\r\n" >&3
# read the header, it ends in a empty line (just CRLF)
while IFS= read -r line ; do
[[ "$line" == $'\r' ]] && break
done <&3
# read the data
nul='\0'
while IFS= read -d '' -r x || { nul=""; [ -n "$x" ]; }; do
printf "%s$nul" "$x"
done <&3
exec 3>&-
}
Usar con download http://path/to/file > file
.
Nos ocupamos de bytes NUL con read -d ''
. Se lee hasta un byte NUL y devuelve verdadero si lo encontró, falso si no lo encontró. Bash no puede manejar bytes NUL en cadenas, por lo que cuando read
regresa con verdadero, agregamos el byte NUL manualmente al imprimir, y cuando devuelve falso, sabemos que ya no hay bytes NUL, y este debería ser el último dato. .
Probado con Bash 4.4 en archivos con NUL en el medio, y que termina en cero, uno o dos NUL, y también con los binarios wget
y curl
de Debian. El wget
binario de 373 kB tardó aproximadamente 5,7 segundos en descargarse. Una velocidad de aproximadamente 65 kB / so un poco más de 512 kb / s.
En comparación, la solución cat de @ 131 termina en menos de 0.1 s, o casi cien veces más rápido. No es muy sorprendente, de verdad.
Esto es obviamente una tontería, ya que sin usar utilidades externas, no hay mucho que podamos hacer con el archivo descargado, ni siquiera hacerlo ejecutable.
gawk