That's a very practical and important question, Labby! Validating argument formats is crucial for making your scripts robust and preventing unexpected errors or security vulnerabilities.
There are many ways to validate argument formats, depending on what type of format you're expecting. Let's look at some common scenarios and how to validate them in Bash.
1. Checking for a specific number of arguments
You've already started exploring this with $#. This is the most basic form of validation.
#!/bin/bash
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <argument1> <argument2>"
exit 1
fi
echo "Two arguments provided: $1 and $2"
$0refers to the name of the script itself, useful for printing usage messages.exit 1is a common convention to indicate that the script terminated with an error.
2. Checking if an argument is a number (integer)
You can use regular expressions or built-in Bash features for this.
Using [[ ... =~ ... ]] (Regex matching):
#!/bin/bash
if [[ ! "$1" =~ ^[0-9]+$ ]]; then
echo "Error: Argument 1 must be an integer."
exit 1
fi
echo "Argument 1 is a valid integer: $1"
^[0-9]+$means "starts with one or more digits and ends with digits."!negates the condition, so! "$1" =~ ^[0-9]+$means "if argument 1 does NOT match the number pattern."
Using grep -q (quieter grep):
#!/bin/bash
echo "$1" | grep -q '^[0-9]\+$'
if [ $? -ne 0 ]; then # Check the exit status of the previous command
echo "Error: Argument 1 must be an integer."
exit 1
fi
echo "Argument 1 is a valid integer: $1"
grep -qruns silently and sets the exit status to0if a match is found, or1if not.$?holds the exit status of the last executed command.
3. Checking if an argument is a valid file or directory
You can use the test command's (or [ ]) file operators.
#!/bin/bash
if [ ! -f "$1" ]; then
echo "Error: Argument 1 must be a valid file."
exit 1
fi
if [ ! -d "$2" ]; then
echo "Error: Argument 2 must be a valid directory."
exit 1
fi
echo "File '$1' exists."
echo "Directory '$2' exists."
-f FILE: True if FILE exists and is a regular file.-d DIRECTORY: True if DIRECTORY exists and is a directory.- Other useful operators:
-r FILE: True if FILE exists and is readable.-w FILE: True if FILE exists and is writable.-x FILE: True if FILE exists and is executable.
4. Checking against a list of allowed values
#!/bin/bash
ALLOWED_COLORS=("red" "green" "blue")
IS_VALID_COLOR=false
for color in "${ALLOWED_COLORS[@]}"; do
if [ "$1" == "$color" ]; then
IS_VALID_COLOR=true
break
fi
done
if [ "$IS_VALID_COLOR" == "false" ]; then
echo "Error: Argument 1 '$1' is not a valid color. Allowed colors: ${ALLOWED_COLORS[*]}"
exit 1
fi
echo "The chosen color is valid: $1"
"${ALLOWED_COLORS[@]}"expands the arrayALLOWED_COLORSinto separate elements, allowing theforloop to iterate over each one.
5. Checking for specific patterns (more complex regex)
Suppose an argument needs to be an email address format (simplified).
#!/bin/bash
# Simple email regex (not exhaustive for all edge cases, but good for common validation)
EMAIL_REGEX="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$"
if [[ ! "$1" =~ $EMAIL_REGEX ]]; then
echo "Error: Argument 1 must be a valid email address."
exit 1
fi
echo "Valid email address: $1"
General Tips for Argument Validation:
- Be specific: The more precisely you can define the expected format, the better your validation will be.
- Provide helpful error messages: Tell the user what they did wrong and how to fix it (e.g., "Usage: script.sh
"). - Fail early: It's good practice to validate arguments at the beginning of your script and exit if they're invalid, rather than letting the script run with bad input and potentially causing unexpected behavior later.
- Use
[[ ... ]]over[ ... ]for string and regex comparisons:[[ ... ]]is a more modern and powerful Bash feature that handles string comparisons and regex matching more reliably, especially with variables that might contain spaces or special characters. Always quote your variables like"$1"inside[[ ]]or[ ]to prevent word splitting issues.
Which type of validation are you most interested in exploring further, Labby?