Bash Tutorial · Bash Scripting · Lesson 21 of 30
Bash Script Arguments and Options
Read positional arguments, validate them, and parse options with getopts.
Positional arguments
$0 is the script name, $1... the arguments, $# the count, and "$@" all of them (quoted, keeps each
argument intact). shift drops the first argument.
Options with getopts
cat > deploy.sh <<'EOF'
#!/usr/bin/env bash
usage() { echo "usage: $0 [-e env] [-n] service..." >&2; exit 2; }
env="staging"; dry_run=false
while getopts ":e:n" opt; do
case $opt in
e) env=$OPTARG ;;
n) dry_run=true ;;
*) usage ;;
esac
done
shift $((OPTIND - 1))
(( $# > 0 )) || usage
for svc in "$@"; do echo "deploy $svc to $env (dry run: $dry_run)"; done
EOF
chmod +x deploy.sh
./deploy.sh api web
./deploy.sh -e prod -n api
./deploy.sh -x api 2>&1 || echo "exit status: $?"
Output
deploy api to staging (dry run: false) deploy web to staging (dry run: false) deploy api to prod (dry run: true) usage: ./deploy.sh [-e env] [-n] service... exit status: 2
Run this on your computer — see “Get Started” for setup.
Print a usage message and exit non-zero on bad input, so callers and CI notice.
Test yourself
What's the difference between "$@" and $*?
None"$@" keeps each argument separate; $* joins and re-splits them$* includes $0"$@" only works in functions
Show answer
Answer: "$@" keeps each argument separate; $* joins and re-splits them