#!/usr/bin/env bash set -euo pipefail usage() { cat <<'USAGE' Copy files via scp with consistent options. Usage: ssh_copy.sh [options] push HOST LOCAL_PATH REMOTE_PATH ssh_copy.sh [options] pull HOST REMOTE_PATH LOCAL_PATH Options: -u, --user USER Override SSH user (or set REMOTE_USER) -p, --port PORT SSH port (default: REMOTE_PORT or 22) -i, --key PATH Identity file (default: REMOTE_KEY) -r, --recursive Copy directories recursively --accept-new Set StrictHostKeyChecking=accept-new --dry-run Print the scp command that would run -h, --help Show help Environment defaults: REMOTE_USER, REMOTE_PORT, REMOTE_KEY Examples: ssh_copy.sh push my-server ./app.tar.gz /tmp/app.tar.gz ssh_copy.sh --user ubuntu pull 10.0.0.1 /var/log/syslog ./syslog USAGE } port="${REMOTE_PORT:-22}" user="${REMOTE_USER:-}" key="${REMOTE_KEY:-}" recursive=false accept_new=false dry_run=false while [[ $# -gt 0 ]]; do case "$1" in -u|--user) user="${2:-}" shift 2 ;; -p|--port) port="${2:-}" shift 2 ;; -i|--key) key="${2:-}" shift 2 ;; -r|--recursive) recursive=true shift ;; --accept-new) accept_new=true shift ;; --dry-run) dry_run=true shift ;; -h|--help) usage exit 0 ;; -*) echo "Unknown option: $1" >&2 usage >&2 exit 2 ;; *) break ;; esac done if [[ $# -lt 4 ]]; then usage >&2 exit 2 fi direction="$1" shift host="$1" shift dest_host="$host" if [[ -n "$user" ]]; then host_no_user="${host#*@}" dest_host="${user}@${host_no_user}" fi scp_opts=(-P "$port" -p) if [[ -n "$key" ]]; then scp_opts+=(-i "$key" -o "IdentitiesOnly=yes") fi if $recursive; then scp_opts+=(-r) fi if $accept_new; then scp_opts+=(-o "StrictHostKeyChecking=accept-new") fi case "$direction" in push) local_path="$1" remote_path="$2" full_cmd=(scp "${scp_opts[@]}" "$local_path" "${dest_host}:${remote_path}") ;; pull) remote_path="$1" local_path="$2" full_cmd=(scp "${scp_opts[@]}" "${dest_host}:${remote_path}" "$local_path") ;; *) echo "Unknown direction: $direction (expected: push|pull)" >&2 usage >&2 exit 2 ;; esac if $dry_run; then printf '%q ' "${full_cmd[@]}" printf '\n' exit 0 fi "${full_cmd[@]}"