Skip to content

Instantly share code, notes, and snippets.

@stuaxo
Last active July 16, 2023 00:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stuaxo/6e4896847af261abf88da4b1063c26b0 to your computer and use it in GitHub Desktop.
Save stuaxo/6e4896847af261abf88da4b1063c26b0 to your computer and use it in GitHub Desktop.
Download a file using intermediate .part file and automatically resume.
#!/bin/bash
# Function to handle the download
download_file() {
local delete_flag="${1:-false}"
local url="$2"
local filename="$3"
# Extract filename from URL if not provided
if [ -z "$filename" ]; then
filename="${url##*/}"
filename="${filename%%\?*}"
fi
if [ -f "$filename" ]; then
# Retrieve remote file information
remote_info=$(curl -sL -I "$url" | tr -d '\r')
read -r _ remote_size <<< "$(grep -i '^Content-Length:' <<< "$remote_info")"
remote_size="${remote_size##*: }"
remote_size="${remote_size//[[:space:]]/}"
read -r _ remote_modified <<< "$(grep -i '^last-modified:' <<< "$remote_info")"
remote_modified="${remote_modified##*: }"
remote_modified="${remote_modified//,/}"
remote_timestamp=$(date -d "$remote_modified" +"%s")
# Retrieve local file information
read -r local_size _ <<< "$(stat -c '%s %n' "$filename")"
read -r local_modified _ <<< "$(stat -c '%y %n' "$filename")"
local_modified="${local_modified%% *}"
local_timestamp=$(date -d "$local_modified" +"%s")
# Compare file sizes and timestamps
if [ "$remote_size" = "$local_size" ] && [ "$remote_timestamp" -le "$local_timestamp" ]; then
echo "Message: File already downloaded."
return
elif [ "$remote_size" = "$local_size" ] && [ "$remote_timestamp" -gt "$local_timestamp" ]; then
echo "Warning: The local file is different from the remote file."
if [ "$delete_flag" = true ]; then
echo "Deleting the local file..."
rm "$filename"
fi
fi
fi
# Start or continue the download
curl -C - -L -o "${filename}.part" --progress-bar "$url"
# Check if the download was successful
if [ "$?" -eq 0 ]; then
mv "${filename}.part" "$filename"
echo "Download completed!"
fi
}
# Print the usage information
print_usage() {
echo "Usage: $0 [-f] <url> [filename]"
echo "Options:"
echo " -f Delete the local file if it differs from the remote file"
}
# Process command line options
if [[ $1 == "-f" ]]; then
delete_flag=true
shift
fi
while getopts ":h" opt; do
case $opt in
h)
print_usage
exit 0
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
esac
done
shift "$((OPTIND - 1))"
# Check if the required arguments are provided
if [ $# -lt 1 ]; then
echo "Error: Missing URL argument."
print_usage
exit 1
fi
# Call the main logic function
download_file "$delete_flag" "$1" "$2"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment