Guide
Bash-Scripting
Intermediate
Command-Line Arguments
Positional parameters, shift, getopts, and parsing both short (-e) and long (--environment) flags in Bash scripts.
Positional Parameters
#!/usr/bin/env bash
# ./deploy.sh myapp production
echo "Script name: $0"
echo "First arg: $1" # myapp
echo "Second arg: $2" # production
echo "All args: $@"
echo "Arg count: $#"
shift — Consuming Arguments One at a Time
while [ "$#" -gt 0 ]; do
echo "Processing: $1"
shift # drops $1, shifts $2 into $1, $3 into $2, etc.
done
Simple Flag Parsing (Manual)
ENVIRONMENT="dev"
VERBOSE=false
while [ "$#" -gt 0 ]; do
case "$1" in
-e|--environment)
ENVIRONMENT="$2"
shift 2
;;
-v|--verbose)
VERBOSE=true
shift
;;
-h|--help)
echo "Usage: $0 [-e environment] [-v]"
exit 0
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done
echo "Environment: $ENVIRONMENT, Verbose: $VERBOSE"
./deploy.sh --environment production --verbose
getopts — The Built-In Option Parser (Short Flags Only)
#!/usr/bin/env bash
ENVIRONMENT="dev"
VERBOSE=false
while getopts "e:vh" opt; do
case "$opt" in
e) ENVIRONMENT="$OPTARG" ;;
v) VERBOSE=true ;;
h) echo "Usage: $0 -e environment [-v]"; exit 0 ;;
\?) echo "Invalid option: -$OPTARG" >&2; exit 1 ;;
esac
done
shift $((OPTIND - 1)) # remove processed options, leaving remaining positional args
echo "Environment: $ENVIRONMENT"
echo "Remaining args: $@"
./deploy.sh -e production -v extra_arg
The : after a letter (like e:) means that option requires a value, captured in $OPTARG. getopts only supports single-character flags — it has no built-in support for --long-flags.
Handling Missing/Required Arguments
if [ "$#" -lt 2 ]; then
echo "Usage: $0 <app_name> <environment>" >&2
exit 1
fi
APP_NAME="$1"
ENVIRONMENT="$2"
Default Values for Optional Arguments
ENVIRONMENT="${1:-dev}" # use $1 if given, else default to "dev"
REGION="${2:-us-east-1}"
A Complete Example
#!/usr/bin/env bash
set -euo pipefail
usage() {
echo "Usage: $0 -e <environment> [-r <region>] [-v]"
exit 1
}
REGION="us-east-1"
VERBOSE=false
while getopts "e:r:vh" opt; do
case "$opt" in
e) ENVIRONMENT="$OPTARG" ;;
r) REGION="$OPTARG" ;;
v) VERBOSE=true ;;
h) usage ;;
\?) usage ;;
esac
done
: "${ENVIRONMENT:?environment is required, use -e}" # fail with a clear message if unset
echo "Deploying to $ENVIRONMENT in $REGION (verbose=$VERBOSE)"
Production Considerations
getoptsis POSIX-portable but only supports short, single-character flags — for long-flag support (--environment), you need manualcase-based parsing (as shown above) or a third-party library.- Always validate required arguments early and
exitwith a clear usage message — silent failures deep in a script are much harder to debug than an immediate, obvious error. shift $((OPTIND - 1))after agetoptsloop is easy to forget — without it,$1still refers to the first parsed option, not the first remaining positional argument.
Quick Interview Answer
“
$1,$2,$@, and$#give access to positional arguments;shiftconsumes them one at a time.getoptsis the built-in, POSIX-portable way to parse short flags like-e value, storing the value in$OPTARG— but it doesn’t support long--flagsyntax, which requires manualcase-based parsing on$1/shift/shift 2instead.”
Common Mistakes
- Forgetting
shift $((OPTIND - 1))after agetoptsloop, leaving$1pointing at an already-processed option. - Assuming
getoptssupports--long-flagsout of the box — it only handles single-character short flags. - Not validating that required arguments were actually provided before using them, leading to confusing downstream errors.
Add More Questions to This Guide
Know a question that should be here? Share it and help the community!
Open Google Form