To parse command-line arguments in Bash, you can use positional parameters ($1
, $2
, etc.), the getopts
built-in (for short options), or the external getopt
command (for long options). Below is a detailed guide with examples.
1. Basic Argument Parsing
Access arguments directly using positional parameters:
$1
,$2
, …: Individual arguments.$#
: Total number of arguments.$@
: All arguments as an array.$0
: Script name.
Example: Simple Script
#!/bin/bash
echo "Script Name: $0"
echo "First Argument: $1"
echo "Second Argument: $2"
echo "All Arguments: $@"
echo "Total Arguments: $#"
Usage:
./script.sh arg1 arg2
2. Using getopts
for Short Options
getopts
is ideal for parsing short options (e.g., -a
, -b value
).
It supports:
- Options with required values (
-f filename
). - Error handling for invalid options.
Example: Parse -a
and -f <file>
#!/bin/bash
while getopts ":af:" opt; do
case $opt in
a)
echo "Option -a triggered"
;;
f)
echo "Option -f has value: $OPTARG"
;;
\?)
echo "Invalid option: -$OPTARG"
exit 1
;;
:)
echo "Option -$OPTARG requires an argument."
exit 1
;;
esac
done
# Shift processed options, leaving non-option arguments
shift $((OPTIND -1))
echo "Remaining arguments: $@"
Usage:
./script.sh -a -f input.txt remaining_arg
Key Points:
:af:
: Options string where:a
is a flag without arguments.f:
expects a value (colon:
indicates required argument).OPTARG
: Value of the option’s argument (e.g.,input.txt
for-f
).OPTIND
: Index of the next argument to process.shift $((OPTIND -1))
: Moves positional parameters past the options.
3. Using getopt
for Long Options
The external getopt
command (not getopts
) supports long options (e.g., --file
).
⚠️ Note: Behavior varies between systems (GNU vs. BSD).
Example: Parse --file <file>
and --verbose
#!/bin/bash
# Parse options with getopt (GNU version)
args=$(getopt -o f:v --long file:,verbose -- "$@") || exit 1
eval set -- "$args"
while true; do
case "$1" in
-f|--file)
echo "File: $2"
shift 2
;;
-v|--verbose)
echo "Verbose mode enabled"
shift
;;
--)
shift
break
;;
*)
echo "Internal error"
exit 1
;;
esac
done
echo "Remaining arguments: $@"
Usage:
./script.sh --file data.txt --verbose remaining_arg
Key Points:
-o f:v
: Short options (-f
with argument,-v
as flag).--long file:,verbose
: Long options (same as short options).eval set -- "$args"
: Reorganizes arguments for processing.--
: Separates options from non-option arguments.
4. Handling Non-Option Arguments
After parsing options, access remaining arguments with $@
:
#!/bin/bash
while getopts ":a" opt; do
# ... process options ...
done
shift $((OPTIND -1))
for arg in "$@"; do
echo "Non-option argument: $arg"
done
5. Best Practices
- Error Handling:
- Use
getopts
‘s\?
and:
cases to handle invalid/missing arguments.
- Portability:
- Prefer
getopts
(POSIX-compliant) for short options. - Use
getopt
cautiously (check for GNU/BSD differences).
- Help Messages:
- Include a
usage()
function for clarity:bash usage() { echo "Usage: $0 [-a] [-f file] [args...]" exit 1 }
Summary
Method | Use Case | Pros | Cons |
---|---|---|---|
Positional | Simple scripts with fixed args | No setup required | Inflexible for options |
getopts | Short options (-a , -f val ) | Built-in, POSIX-compliant | No long option support |
getopt | Long options (--file ) | Supports long options | Not POSIX; system-dependent |
Example Workflow
- Define Options:
while getopts ":ab:c" opt; do
case $opt in
a) echo "Flag -a";;
b) echo "Option -b with $OPTARG";;
c) echo "Flag -c";;
\?) echo "Invalid option"; exit 1;;
esac
done
- Process Remaining Args:
shift $((OPTIND -1))
echo "Remaining args: $@"
Use these techniques to build robust CLI tools in Bash!