← Back to Bash Course | Chapter 12: Error Handling & Debugging | Lesson 12 of 12

Validating Script Input and Arguments

Before a script uses the values someone passed in, it should check that those values actually look right, instead of assuming they will always be correct.

Checking the Argument Count

$# holds the number of positional parameters passed to the script (or function). Checking it up front catches missing arguments before they cause confusing errors later.

Example: Checking the Argument Count

bash
#!/bin/bash
set -- "only_one_arg"
if [[ $# -lt 2 ]]; then
    echo "warning: expected 2 arguments, got $#" >&2
else
    echo "got both arguments: $1 and $2"
fi

Requiring a Value with :?

${var:?message} expands to var's value normally, but if var is unset or empty, it prints message to stderr and causes the script to exit immediately, which is a compact one-line required-argument check.

Example: Requiring a Value with :?

bash
#!/bin/bash
set -- "config.yaml"
file=${1:?usage: script.sh <filename>}
echo "processing file: $file"

Validating a Value's Shape

Beyond checking that a value is present, scripts should confirm it has the expected shape, such as being purely numeric, using a regex match before relying on it in arithmetic.

Example: Validating a Value's Shape

bash
#!/bin/bash
validate_number() {
    if [[ $1 =~ ^-?[0-9]+$ ]]; then
        echo "$1 is a valid integer"
        return 0
    else
        echo "'$1' is not a valid integer" >&2
        return 1
    fi
}

validate_number "42"
validate_number "abc" || echo "validation correctly rejected non-numeric input"

A Usage Message on Bad Input

When validation fails, printing a clear usage message to stderr and exiting non-zero gives the caller (a human or another script) an immediate, actionable explanation instead of a cryptic downstream failure.

Example: A Usage Message on Bad Input

bash
#!/bin/bash
usage() {
    echo "Usage: $0 <name> <count>" >&2
    exit 1
}

set -- "widget"
if [[ $# -ne 2 ]]; then
    ( usage ) 2>/dev/null
    echo "usage check failed as expected with $# argument(s)"
fi
Common Mistakes
  1. Using a positional parameter like $1 without first checking it was actually provided, leading to confusing downstream errors instead of a clear message.
  2. Validating that an argument is non-empty but not that it has the right shape (e.g. checking a number is not blank but not that it's actually numeric).
  3. Failing silently instead of printing a clear usage message and a non-zero exit code when validation fails.
Chapter Summary
  • ${1:?message} immediately errors with message if $1 is unset or empty, without needing a separate if check.
  • $# holds the number of positional parameters, so it can be checked before using specific ones.
  • Regex or arithmetic checks confirm a value's shape (numeric, matches a pattern), not just that it's non-empty.
  • A good validation failure prints a usage message to stderr and exits non-zero, rather than continuing with bad data.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.