Skip to content

Instantly share code, notes, and snippets.

@tcely
Created January 16, 2018 16:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tcely/d99dd478e6780d872e1e6d500575a582 to your computer and use it in GitHub Desktop.
Save tcely/d99dd478e6780d872e1e6d500575a582 to your computer and use it in GitHub Desktop.
Download a file when its ETag changes. Useful for GitHub (which doesn't respect If-Modified-Since).
#!/bin/bash
conditional_get_etag() {
local _url _file _tmpdir
local _awk_program='/^ETag:/ {$1=""; printf "If-None-Match: %s", substr($0, 2, length($0)-2); exit;}'
for _url; do
if [ '--file=' = "${_url:0:7}" ]; then
_file="${_url:7}"
continue
fi
if [ -z "$_file" ]; then
_tmpdir="$(mktemp -d --tmpdir .curl-filename-XXXXXX || { mkdir -p '.tmp' && echo '.tmp'; })"
fi
if [ -n "$_tmpdir" ] && cd "$_tmpdir"; then
# This is a guess, but doesn't hurt if we're wrong.
cp 2>/dev/null ~-/"$(basename "$_url").headers" '.headers'
curl > '.filename' -JLORSs -w '%{filename_effective}\n' -H "$(awk 2>/dev/null "$_awk_program" ".headers")" -D '.headers' "$_url"
_file="$( < .filename )"
[ -n "$_file" ] || _file="$(basename "$_url")"
if [ -s "$_file" ]; then
mv "$_file" ~-/"${_file}.tmp" && mv '.headers' ~-/"${_file}.tmp.headers"
fi
cd - >/dev/null
rm -rf "$_tmpdir"
else
curl -JLRSs -H "$(awk 2>/dev/null "$_awk_program" "${_file}.headers")" -D "${_file}.tmp.headers" -o "${_file}.tmp" "$_url"
fi
unset -v _tmpdir
if [ -s "${_file}.tmp" ]; then
[ ! -f "$_file" ] || chown -v --reference "$_file" "${_file}.tmp"
[ ! -f "$_file" ] || chmod -v --reference "$_file" "${_file}.tmp"
mv -v "${_file}.tmp" "$_file"
mv -v "${_file}.tmp.headers" "${_file}.headers"
fi
rm -f "${_file}.tmp.headers" "${_file}.tmp"
unset -v _file
done; unset -v _url
}
conditional_get_etag "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment