Строго говоря, « просто Bash и ничего больше », вот одна адаптация более ранних ответов ( @ Chris's , @ 131's ), которая не вызывает никаких внешних утилит (даже стандартных), но также работает с двоичными файлами:
#!/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>&-
}
Используйте с download http://path/to/file > file
.
Мы имеем дело с NUL байтами read -d ''
. Он читает до байта NUL и возвращает true, если он нашел, и false, если нет. Bash не может обрабатывать NUL-байты в строках, поэтому, когда read
возвращается с true, мы добавляем NUL-байт вручную при печати, а когда он возвращает false, мы знаем, что больше нет NUL-байтов, и это должно быть последним фрагментом данных. ,
Испытано с Bash 4.4 на файлах с NULs в середине, и заканчивается в ноль, один или два NULs, а также с wget
и curl
двоичные файлы из Debian. wget
Загрузка двоичного файла объемом 373 КБ заняла около 5,7 секунд. Скорость около 65 кБ / с или чуть больше 512 кб / с.
Для сравнения, решение @ 131 для cat завершается менее чем за 0,1 с, или почти в сто раз быстрее. Не очень удивительно, правда.
Это, очевидно, глупо, поскольку без использования внешних утилит мы мало что можем сделать с загруженным файлом, даже не сделать его исполняемым.
gawk