Thực hiện nghiêm túc " chỉ Bash và không có gì khác ", đây là một bản phóng tác của các câu trả lời trước đó ( @ Chris , @ 131 ) không gọi bất kỳ tiện ích bên ngoài nào (thậm chí không phải là tiêu chuẩn) mà còn hoạt động với các tệp nhị phân:
#!/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>&-
}
Sử dụng với download http://path/to/file > file
.
Chúng tôi xử lý các byte NUL với read -d ''
. Nó đọc cho đến một byte NUL và trả về true nếu tìm thấy một byte, sai nếu không. Bash không thể xử lý các byte NUL trong chuỗi, vì vậy khi read
trả về bằng true, chúng ta thêm byte NUL theo cách thủ công khi in và khi nó trả về false, chúng ta biết không còn byte NUL nào nữa và đây sẽ là phần dữ liệu cuối cùng .
Đã thử nghiệm với Bash 4.4 trên các tệp có NUL ở giữa và kết thúc bằng 0, một hoặc hai NUL và cả với các nhị phân wget
và curl
Debian từ Debian. wget
Nhị phân 373 kB mất khoảng 5,7 giây để tải xuống. Tốc độ khoảng 65 kB / s hoặc hơn một chút so với 512 kb / s.
So sánh, dung dịch mèo của @ 131 kết thúc sau chưa đầy 0,1 giây, hoặc nhanh hơn gần một trăm lần. Không có gì đáng ngạc nhiên, thực sự.
Điều này rõ ràng là ngớ ngẩn, vì không sử dụng các tiện ích bên ngoài, chúng ta không thể làm gì nhiều với tệp đã tải xuống, thậm chí không thể thực hiện được.
gawk