En prenant strictement le " juste Bash et rien d' autre ", voici une adaptation des réponses précédentes ( @ Chris's , @ 131 ) qui n'appelle aucun utilitaire externe (même les plus classiques) mais fonctionne également avec des fichiers binaires:
#!/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>&-
}
Utilisez avec download http://path/to/file > file
.
Nous traitons avec les octets NUL avec read -d ''
. Il lit jusqu'à un octet NUL et renvoie true s'il en a trouvé un, false s'il ne l'a pas trouvé. Bash ne peut pas gérer les octets NUL dans les chaînes. Ainsi, lorsqu'il read
renvoie true, nous ajoutons manuellement l'octet NUL lors de l'impression et lorsqu'il renvoie false, nous savons qu'il n'y a plus d'octets NUL, ce qui devrait être la dernière donnée. .
Testé avec Bash 4.4 sur des fichiers avec des NUL au milieu et se terminant par zéro, un ou deux NUL, ainsi qu'avec les binaires wget
et les curl
binaires de Debian. Le wget
téléchargement du fichier binaire de 373 ko a pris environ 5,7 secondes. Une vitesse d'environ 65 ko / s ou un peu plus de 512 ko / s.
En comparaison, la solution cat de @ 131 se termine en moins de 0,1 s, soit presque cent fois plus vite. Pas très surprenant, vraiment.
C'est évidemment idiot, car sans utiliser d'utilitaires externes, nous ne pouvons pas faire grand chose avec le fichier téléchargé, pas même le rendre exécutable.
gawk