How to pass arguments to a Bash script
Pass arguments to a Bash script using $1..$9, $@, getopts for flags, and shift for processing. A practical guide with defaults and validation patterns.
Tldr
Inside the script, positional arguments are $1, $2, $3 (up to $9 unbraced; ${10} after that). $@ is all of them as separate words, $# is the count. For named flags (`--verbose`), use getopts (POSIX, single-letter) or a manual while/case loop (long options).
Intro
Passing arguments to a Bash script is one of those things every shell programmer half-knows. Here is the full picture: positional access, validation, defaults, and named flags.
Steps
Name
Access positional arguments
Text
Bash exposes arguments as numbered variables. Always quote them — unquoted $1 is split on whitespace.
Name
Validate the count
Text
Bail out early with a usage message and a non-zero exit code if required arguments are missing.
Name
Provide defaults
Text
Use parameter expansion to default optional arguments. ${1:-value} expands to "value" when $1 is unset or empty.
Name
Loop over all arguments
Text
Use "$@" — always quoted — to iterate over arguments while preserving spaces and special characters in each one.
Name
Parse named flags with getopts
Text
getopts handles single-letter flags (-v, -o file). It is POSIX and built into Bash. Long options (--verbose) require a manual loop or external getopt.
Name
Parse long options manually
Text
For --verbose / --output=foo style flags, hand-roll a while/case loop. It is more code than getopts but works on every shell.
Faq
Q
What is the difference between $@ and $*?
A
When quoted, "$@" expands to each argument as a separate word — "arg one" stays one word. "$*" joins all arguments into a single word separated by the first character of IFS. Almost always use "$@".
Q
Why $10 not working?
A
Bash parses $10 as $1 followed by literal 0. For arguments past 9, brace it: ${10}, ${11}, etc.
Q
How do I pass arrays?
A
You cannot pass an array directly. Pass it as separate arguments and reconstruct with `arr=("$@")` inside the function, or export it as a string and split.