Positional Parameters and Argument Handling
Scripts receive data from the caller via positional parameters. Learn how to access, validate, and process script arguments robustly.
January 24, 20266 min read
BashArgumentsScripting
Positional parameters are how callers pass information to your script. Understanding all the ways to access, validate, and iterate over them lets you write scripts with clean, intuitive command-line interfaces.
Accessing Arguments
#!/usr/bin/env bash
# Called as: ./script.sh one two three four five
echo "$0 = $0" # ./script.sh (script name)
echo "$1 = $1" # one
echo "$2 = $2" # two
echo "$# = $#" # 5
echo "$@ = $@" # one two three four five
echo "$* = $*" # one two three four five
# Access argument 10+: use braces
# echo "${10}" # would give the 10th argument
# All args in a loop (preserves spaces in individual args)
for arg in "$@"; do
echo " arg: $arg"
doneValidation Patterns
#!/usr/bin/env bash
function usage {
cat >&2 <<-EOF
Usage: $0 [OPTIONS] <source> <destination>
Options:
-v Verbose
-h Show this help
Arguments:
source Path to input file
destination Path to output directory
EOF
exit 1
}
# Require minimum arguments
if [[ $# -lt 2 ]]; then
echo "ERROR: Too few arguments" >&2
usage
fi
# Require exactly N arguments
if [[ $# -ne 2 ]]; then
echo "ERROR: Expected exactly 2 arguments, got $#" >&2
usage
fiDefault Argument Values
#!/usr/bin/env bash
# Set defaults if not provided
host="${1:-localhost}"
port="${2:-8080}"
timeout="${3:-30}"
echo "Connecting to $host:$port (timeout: ${timeout}s)"
# Require argument or exit with message
config="${1:?Usage: $0 <config-file>}"
# Multiple defaults in one go
input_file="${1:-/dev/stdin}"
output_dir="${2:-./output}"
log_level="${3:-info}"Processing All Arguments
#!/usr/bin/env bash
# Script that accepts any number of files
if [[ $# -eq 0 ]]; then
echo "Usage: $0 <file> [file...]" >&2
exit 1
fi
processed=0
failed=0
for file in "$@"; do
if [[ ! -f "$file" ]]; then
echo "Skipping (not a file): $file" >&2
(( failed++ ))
continue
fi
echo "Processing: $file"
# ... do work ...
(( processed++ ))
done
echo ""
echo "Done: $processed processed, $failed skipped"set -- to Replace Arguments
# set -- replaces positional parameters
set -- "new_first" "new_second" "new_third"
echo "$1" # new_first
echo "$2" # new_second
# Useful for normalising arguments
# E.g., split "host:port" into $1 and $2
pair="localhost:5432"
IFS=: read -r host port <<< "$pair"
set -- "$host" "$port"
echo "$1" # localhost
echo "$2" # 5432Quick Check
How do you access the 11th positional argument in a Bash script?
Exercise
Write a script word-count.sh that:
- Accepts one or more filenames as arguments
- For each file: prints "filename: N words"
- At the end, prints the total word count across all files
- If a file doesn't exist, skip it with a warning