Shell Variables   «Prev  Next»
Lesson 2Accessing command-line arguments
ObjectiveRead, validate, and iterate over command-line arguments in modern Bash scripts using positional parameters and idiomatic parsing.

Accessing Command-line Arguments (Modern Bash)

Many UNIX utilities change behavior based on parameters (for example, ls -a or ls -l). Your shell scripts can do the same by reading command-line arguments—values supplied after the script name. Bash exposes these as positional parameters: $0 (script/command name), $1, $2, …, ${10}, and so on.

Quick start

# convert <options> <files...>
echo "Script: $0"
echo "First arg: $1"
echo "Count: $#"
echo "All (split into words by IFS): $*"
echo "All (preserve each arg): $@"

Tip: Always quote expansions in loops; prefer "$@" to preserve each argument exactly (including spaces).

Positional parameters by example

Suppose you run the command below; the figures (kept from the legacy lesson) illustrate how Bash fills each parameter:

% convert -all tickets.dat agents.dat clients.dat

Slide show: parameters in action

1) convert -all tickets.dat agents.dat clients.dat
1) Command line entered: convert -all tickets.dat agents.dat clients.dat

2) $0 = convert
2) $0 = convert

3) $1 = -all
3) $1 = -all
convert -all tickets.dat agents.dat clients.dat

$0=convert
$1=-all

Why it matters: $1 is the first argument after the command name.


4) $2 = tickets.dat
4) $2 = tickets.dat
convert -all tickets.dat agents.dat clients.dat

$0=convert
$1=-all
$2=tickets.dat

5) $3 = agents.dat
5) $3 = agents.dat

6) $4 = clients.dat
6) $4 = clients.dat

7) $# = 4
7) $# = 4 (number of arguments, excluding $0)

8) $* and $@ expanded
8) $* and $@:
convert -all tickets.dat agents.dat clients.dat
$0=convert
$1=-all
$2=tickets.dat
$3=agents.dat
$4=clients.dat
$#=4
$*=convert -all tickets.dat agents.dat clients.dat
  • $* → all args as one word when quoted ("$*").
  • $@ → each arg as its own word when quoted ("$@") — best for loops.

Iterating over arguments safely

# Process each file argument exactly as passed (handles spaces)
for f in "$@"; do
  printf 'Converting: %s\n' "$f"
done

More than nine arguments

echo "Tenth argument is: ${10}"

Use braces for two-digit indexes (e.g., ${11}).

Shifting through arguments

# Example: handle an optional -a/--all flag, then files
all=false
while [ $# -gt 0 ]; do
  case "$1" in
    -a|--all) all=true; shift ;;
    --) shift; break ;;   # end of options
    -*) echo "Unknown option: $1" >&2; exit 2 ;;
    *)  break ;;          # first non-option
  esac
done

# Remaining "$@" are the files
"$all" && echo "Converting all formats"
for f in "$@"; do
  printf 'Convert: %s\n' "$f"
done

Using getopts for short options

# Supports: -a (all), -o <outdir>
all=false; outdir="."
while getopts ":ao:" opt; do
  case "$opt" in
    a) all=true ;;
    o) outdir=$OPTARG ;;
    \?) echo "Invalid option: -$OPTARG" >&2; exit 2 ;;
    :)  echo "Option -$OPTARG requires an argument" >&2; exit 2 ;;
  esac
done
shift $((OPTIND - 1))  # drop parsed options

for f in "$@"; do
  printf 'Convert: %s → %s\n' "$f" "$outdir"
done

Common pitfalls


SEMrush Software 2 SEMrush Banner 2