diff --git a/bin/send_dir.sh b/bin/send_dir.sh new file mode 100755 index 0000000..13d53dd --- /dev/null +++ b/bin/send_dir.sh @@ -0,0 +1,90 @@ +#!/usr/bin/env bash +# +# send_dir.sh — upload every file in a directory to a running FileServer. +# +# Each file is POSTed to /upload as multipart/form-data. By default one file per +# request (so you get per-file feedback); use -b to batch all files into a +# single request instead. +# +# Usage: +# bin/send_dir.sh [-u URL] [-b] [-r] DIR +# +# DIR directory whose files are uploaded +# -u URL server base URL (default: http://127.0.0.1:8080, or $FS_URL) +# -b batch: send all files in one multipart request +# -r recurse into subdirectories +# +# Examples: +# bin/send_dir.sh data/samples +# bin/send_dir.sh -u http://host:9000 -b -r ~/Downloads +set -euo pipefail + +url="${FS_URL:-http://127.0.0.1:8080}" +batch=0 +recurse=0 + +while getopts ":u:brh" opt; do + case "$opt" in + u) url="$OPTARG" ;; + b) batch=1 ;; + r) recurse=1 ;; + h) sed -n '2,20p' "$0"; exit 0 ;; + \?) echo "unknown option: -$OPTARG" >&2; exit 2 ;; + :) echo "option -$OPTARG needs an argument" >&2; exit 2 ;; + esac +done +shift $((OPTIND - 1)) + +dir="${1:-}" +if [[ -z "$dir" ]]; then + echo "usage: $0 [-u URL] [-b] [-r] DIR" >&2 + exit 2 +fi +if [[ ! -d "$dir" ]]; then + echo "not a directory: $dir" >&2 + exit 2 +fi + +endpoint="${url%/}/upload" + +# Collect regular files (optionally recursive), NUL-safe for odd filenames. +mapfile -d '' files < <( + if [[ "$recurse" -eq 1 ]]; then + find "$dir" -type f -print0 + else + find "$dir" -maxdepth 1 -type f -print0 + fi +) + +if [[ "${#files[@]}" -eq 0 ]]; then + echo "no files found in $dir" >&2 + exit 1 +fi + +echo "uploading ${#files[@]} file(s) from '$dir' to $endpoint" + +if [[ "$batch" -eq 1 ]]; then + # One request with every file. Each -F field name is arbitrary; the server + # keys off the filename, so we just number them. + args=() + i=0 + for f in "${files[@]}"; do + args+=(-F "f${i}=@${f}") + i=$((i + 1)) + done + code=$(curl -sS -o /dev/stderr -w '%{http_code}' "${args[@]}" "$endpoint") + echo + echo "-> HTTP $code" + [[ "$code" == "202" ]] +else + # One request per file. + ok=0 + fail=0 + for f in "${files[@]}"; do + code=$(curl -sS -o /dev/stderr -w '%{http_code}' -F "file=@${f}" "$endpoint") + echo " -> HTTP $code ${f}" + if [[ "$code" == "202" ]]; then ok=$((ok + 1)); else fail=$((fail + 1)); fi + done + echo "done: $ok accepted, $fail failed" + [[ "$fail" -eq 0 ]] +fi