When writing shell scripts, handling command-line options effectively is essential. A common scenario developers encounter is needing to process the same command-line option multiple times within a script. While many basic tutorials cover simple option parsing, fewer resources explain clearly how to handle repeated options. This tutorial will demonstrate how to process a repeated option multiple times in your shell script clearly and effectively.
We’ll cover the most common tools (getopts
, manual parsing, and advanced parsing using getopt
) and provide practical examples and insights to help you choose the best solution for your situation.
Why Is Handling Repeated Options Important?
Repeated options allow users to pass multiple values for the same option, making scripts flexible and user-friendly. For example, consider a backup script that needs to accept multiple directories to back up, each specified by a separate -d
option:
./backup.sh -d /etc -d /home -d /var/log
Supporting repeated options is crucial for scripts designed for flexible, real-world use.
Method 1: Using getopts
to Handle Repeated Options
The built-in getopts
command is one of the most common and straightforward ways to handle command-line options. However, getopts
doesn’t natively support repeated options. To use it effectively, you must manually store repeated arguments in an array.
Here’s a practical example demonstrating how you can handle repeated options with getopts
:
Example Script:
#!/bin/bash
# Initialize an empty array to store directories
declare -a directories
# Parse command-line options using getopts
while getopts ":d:" opt; do
case ${opt} in
d )
directories+=("$OPTARG")
;;
\? )
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
: )
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
# Example of using the collected values
echo "Directories to back up:"
for dir in "${directories[@]}"; do
echo " - $dir"
done
Explanation:
- We initialize an empty bash array named
directories
. - Each time the
-d
option is encountered, its argument ($OPTARG
) is pushed into thedirectories
array. - After parsing, we loop through the array and process each directory individually.
Running the Script:
./backup.sh -d /etc -d /home -d /var/log
Output:
Directories to back up:
- /etc
- /home
- /var/log
Method 2: Manual Parsing for Repeated Options
In some environments or scripts, you may prefer manual parsing due to its simplicity and flexibility. Here’s how you might do it:
Example Script:
#!/bin/bash
declare -a directories
# Loop through all arguments manually
while [[ $# -gt 0 ]]; do
case "$1" in
-d|--directory)
if [[ -n "$2" && ! "$2" =~ ^- ]]; then
directories+=("$2")
shift 2
else
echo "Error: '-d|--directory' requires a non-empty option argument." >&2
exit 1
fi
;;
*)
echo "Invalid option: $1" >&2
exit 1
;;
esac
done
# Example processing
echo "Directories specified:"
for dir in "${directories[@]}"; do
echo " - $dir"
done
Explanation:
- We loop manually through arguments using a
while
loop and$#
(argument count). - Each time we encounter the
-d
or--directory
option, we store the next argument into our array. - We ensure the argument is not missing and not another option (not starting with a
-
).
Running the Script:
./backup.sh -d /etc --directory /home -d /var/log
Output:
Directories specified:
- /etc
- /home
- /var/log
Method 3: Using Enhanced getopt
for Repeated Options
The enhanced getopt
command (GNU getopt) supports repeated options more naturally and handles short and long-form options. Here’s how you can leverage it:
Example Script:
#!/bin/bash
OPTIONS=$(getopt -o d: -l directory: -- "$@")
if [ $? -ne 0 ]; then
echo "Incorrect options provided" >&2
exit 1
fi
eval set -- "$OPTIONS"
declare -a directories
while true; do
case "$1" in
-d|--directory)
directories+=("$2")
shift 2
;;
--)
shift
break
;;
*)
echo "Unexpected option: $1" >&2
exit 1
;;
esac
done
# Example processing
echo "Directories collected via getopt:"
for dir in "${directories[@]}"; do
echo " - $dir"
done
Explanation:
getopt
parses both short (-d
) and long (--directory
) options.- It rearranges the command-line arguments into a standardized format.
- The script handles the
-d
/--directory
option repeatedly, storing each occurrence in the array.
Running the Script:
./backup.sh -d /etc --directory /home -d /var/log
Output:
Directories collected via getopt:
- /etc
- /home
- /var/log
Comparing the Methods
Method | Advantages | Disadvantages |
---|---|---|
getopts | Built-in, simple syntax | Limited to single-letter options |
Manual parsing | Maximum flexibility and portability | More verbose, error-prone |
Enhanced getopt | Supports short/long options, easier parsing | Less portable (GNU/Linux-specific) |
Choose according to your script’s complexity, portability requirements, and readability preferences.
Conclusion
Processing repeated command-line options is a common, practical requirement in shell scripting. This tutorial presented three effective ways to handle repeated options: built-in getopts
, manual parsing, and enhanced getopt
. Each has its strengths and weaknesses, so choose the method best suited to your scripting needs and environment.
By clearly handling repeated options, your scripts become more robust, flexible, and user-friendly.
Sources and Further Reading
- Unix Stack Exchange: Need shell script help - processing the same option multiple times
- GNU Getopt Documentation
- Bash Reference Manual - Arrays
**