-
-
Save nilium/9ece98f861474c8dc6acc948518299a5 to your computer and use it in GitHub Desktop.
Short script to upload a file to a GCS bucket and print its public URL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
prog="$(basename "$0")" | |
## Defaults | |
# : ${FUP_BUCKET:=YOUR-BUCKET} | |
# : ${FUP_URL_PREFIX:=https://CUSTOM-URL/} | |
: ${FUP_PAR_UPLOAD_THRESHOLD:=100M} | |
: ${FUP_URL_PREFIX:=https://storage.googleapis.com/${FUP_BUCKET}/} | |
## Support functions | |
usage() { | |
cat <<EOF | |
Usage: ${prog} [OPTIONS] [--] [FILE...] | |
Upload a file to a Google Cloud Storage bucket with a SHA2 base64 | |
directory prefix. If file is '-' (or /dev/stdin), or no file is given, | |
fup will read stdin to a temporary file and upload it as a 'stdin' file. | |
You can set the FUP_BUCKET and FUP_SHASUM environment variables to | |
declare a default bucket (-b) and shasum program (-c). FUP_SHASUM | |
defaults to the first available of shasum, sha224sum, or sha3-224sum. | |
Other environment variables are listed in the options below. | |
Options: | |
-b <BUCKET> Set the bucket to copy files to. Can have a path prefix. | |
Required if FUP_BUCKET is not set. May not contain | |
a trailing slash. | |
-c <PROG> Program command-line for computing a checksum from a file. | |
Must output one line in shasum format. | |
Defaults to a sha224sum program if FUP_SHASUM is not set. | |
-t <THR> Sets the parallel upload threshold used by gsutil. | |
Defaults to 100M if FUP_PAR_UPLOAD_THRESHOLD is not set. | |
-u <URL> Set the URL prefix printed by $prog. | |
Defaults to the Google storage bucket's URL if | |
FUP_URL_PREFIX is not set. | |
-p Copy file URL(s) to clipboard. | |
-P Do not copy file URL(s) to clipboard (default). | |
Overrides previous uses of -p. | |
-v Emit gsutil progress output. | |
-V Do not emit gsuitl progress output (default). | |
Overrides previous uses of -v. | |
-h, --help Print this usage text. | |
EOF | |
exit 2 | |
} | |
FATAL() { | |
local ec="$1" | |
shift | |
echo 'ERR' "$@" 1>&2 | |
exit "$ec" | |
} | |
bsum() { | |
if ! sum="$($FUP_SHASUM "$@")"; then | |
return 1 | |
fi | |
echo -n "$sum" | | |
awk '{print $1}' | | |
xxd -r -p | base64 | | |
tr /+ _- | tr -d = | | |
sed -e 's/^\(.\)\(.\)/\1\/\2\//' | |
} | |
upload() { | |
local desc="$1" | |
local file="${desc%%:*}" | |
local istmp=0 | |
# Special case standard input | |
if [[ "$file" = - ]] || [[ "$file" = /dev/stdin ]]; then | |
istmp=1 | |
if ! file="$(mktemp)"; then | |
FATAL 1 "Cannot create temporary file for standard input" | |
fi | |
cat > "$file" | |
desc=stdin | |
fi | |
if [[ ! -f "$file" ]]; then | |
FATAL 1 "Cannot upload non-file: $file" | |
fi | |
local name="$(basename "${desc#*:}")" | |
if ! sum="$(bsum "$file" | awk '{print $1}')"; then | |
FATAL 1 "Unable to get the checksum of $name" | |
fi | |
local path="${sum}/$name" | |
local gspath="gs://$FUP_BUCKET/$path" | |
if ! gsutil $quiet -o "GSUtil:parallel_composite_upload_threshold=$FUP_PAR_UPLOAD_THRESHOLD" cp -- "$file" "$gspath" 1>&2; then | |
FATAL 1 "Unable to upload $name" | |
fi | |
if ! gsutil $quiet acl ch -u AllUsers:R "$gspath" 1>&2; then | |
if [[ "$istemp" = 1 ]] && [[ -f "$file" ]]; then | |
rm "$file" | |
fi | |
FATAL 1 "Unable to set ACL on $gspath to publicly readable" | |
fi | |
if [[ "$istemp" = 1 ]] && [[ -f "$file" ]]; then | |
rm "$file" | |
fi | |
printf '%s%s%s' "$FUP_URL_PREFIX" "$path" | |
} | |
## Main | |
if [[ -z "$(command -v gsutil)" ]]; then | |
FATAL 1 $'gsutil not found in PATH. Please install the Google Cloud SDK:\n\n\thttps://cloud.google.com/sdk/install' | |
fi | |
tmpout=/dev/null | |
pasteprefix= | |
paste=0 | |
quiet=-q | |
while [ $# -gt 0 ]; do | |
case "$1" in | |
-b) FUP_BUCKET="$2"; shift;; | |
-b=*) FUP_BUCKET="${1#-b=}";; | |
-b?*) FUP_BUCKET="${1#-b}";; | |
-c) FUP_SHASUM="$2"; shift;; | |
-c=*) FUP_SHASUM="${1#-c=}";; | |
-c?*) FUP_SHASUM="${1#-c}";; | |
-t) FUP_PAR_UPLOAD_THRESHOLD="$2"; shift;; | |
-t=*) FUP_PAR_UPLOAD_THRESHOLD="${1#-t=}";; | |
-t?*) FUP_PAR_UPLOAD_THRESHOLD="${1#-t}";; | |
-u) FUP_URL_PREFIX="$2"; shift;; | |
-u=*) FUP_URL_PREFIX="${1#-u=}";; | |
-u?*) FUP_URL_PREFIX="${1#-u}";; | |
# Toggles | |
-p) paste=1;; | |
-P) paste=0;; | |
-v) quiet=;; | |
-V) quiet=-q;; | |
-h|--help) usage;; | |
--) shift; break;; | |
*) break;; | |
esac | |
shift | |
done | |
if [[ -z "$FUP_BUCKET" ]]; then | |
FATAL 2 'FUP_BUCKET is not set -- it must be set to a GCS bucket name' | |
elif [[ "$FUP_BUCKET" = */ ]]; then | |
FATAL 2 'FUP_BUCKET may not contain a trailing slash' | |
fi | |
# Set default shasum | |
if [ -z "$FUP_SHASUM" ]; then | |
if [ -n "$(command -v sha224sum)" ]; then | |
FUP_SHASUM='sha224sum' | |
elif [ -n "$(command -v gsha224sum)" ]; then | |
FUP_SHASUM='gsha224sum' | |
elif [ -n "$(command -v shasum)" ]; then | |
FUP_SHASUM='shasum -a224' | |
elif [ -n "$(command -v sha3-224sum)" ]; then | |
# Just because we want something with some length here | |
FUP_SHASUM=sha3-224sum | |
else | |
FATAL 1 'None of sha224sum, shasum, nor sha3-224sum are available' | |
fi | |
fi | |
if [[ $# -eq 0 ]]; then | |
set -- - | |
fi | |
if [[ "$1" = -p ]]; then | |
shift | |
paste=1 | |
fi | |
if [[ $paste -eq 1 ]]; then | |
if ! tmpout="$(mktemp)"; then | |
FATAL 1 "Cannot create temporary URLs file" | |
fi | |
trap 'rm "$tmpout"' EXIT | |
fi | |
for file; do | |
if ! url="$(upload "$file")"; then | |
FATAL 1 "Upload failed: $file" | |
fi | |
echo "$url" | |
if [[ $paste -eq 1 ]]; then | |
printf "%s%s" "$pasteprefix" "$url" >>"$tmpout" | |
pasteprefix=$'\n' | |
fi | |
done | |
if [[ $paste -eq 1 ]]; then | |
# TODO: Add checks for x11 clipboard managers | |
<"$tmpout" pbcopy | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment