S3 Bash Tools Part 3
In case of errors/warnings, write your output to stderr and not just echo them to stdout stream. This might also include you returning the usage section.

Having a chain of if block is imo, always very bad. You can use a switch-case block there, and keep shifting the arguments. A simple example would be:

ARGS=()
while [[ $# -gt 0 ]]
do
    key="$1"

    case $key in
      -v|--verbose)
        verbose='/dev/stdout'
        shift # past argument
        ;;
      --dryrun)
        dryrun=1
        shift # past argument
        ;;
      -k=*|--key=*)
        access="${key#*=}"
        shift # past argument
        shift # past value
        ;;
      -k|--key)
        shift # past argument
        access="$1"
        shift # past value
        ;;
      .
      .
      .
      *)    # unknown option
        if [[ "${key#-}" != ${key} ]]; then
            badflag=1
            &gt;&amp;2 echo "Bad flag: ${var}"
        fi
        ARGS+=("$1") # save it in an array for later
        shift # past argument
        ;;
    esac
done


Notice how easily you can maintain the --key=KEY and --key KEY format parameters. Apart from that, it is really easy to later on add another new argument to your utility.

Keep defining your globals in UPPER_CASE, so that it easy to distinguish them later in your ever-expanding code.


echo "These can be set in the environment variables AMZ_ACCESS_KEY/AMZ_SECRET_KEY or passed with flags"



AWS recommends having the environment variables named AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. I would consider it breaking the norm if you are not respecting defaults.

Define the usage content (or man page?) as a heredoc:

USAGE=&lt;&lt;EOF

Usage:
s3cp  &lt;file&gt; &lt;s3-url&gt; [--key=&lt;key&gt;] [--secret=&lt;secret&gt;] [--verbose] [--dryrun]
s3cp  &lt;s3-url&gt; &lt;file&gt; [--key=&lt;key&gt;] [--secret=&lt;secret&gt;] [--verbose] [--dryrun]

s3-url:  s3://&lt;bucket&gt;/&lt;Object-Path&gt;

EOF