LESSON · 1 OF 5

Positional arguments

Positional arguments

Every argument passed to a script becomes a numbered variable inside it.

The basics

bash
#!/bin/bash
echo "script: $0"       # script name (the path used to invoke it)
echo "first:  $1"
echo "second: $2"
echo "count:  $#"
echo "all:    $@"

Run it:

bash
./greet.sh alice bob charlie
# script: ./greet.sh
# first:  alice
# second: bob
# count:  3
# all:    alice bob charlie

Key pieces:

  • $0 is the script name.
  • $1 through $9 are the first nine arguments. For the 10th and beyond you need braces: ${10}, ${11}.
  • $# is the count of arguments.
  • $@ and $* are both "all arguments" but behave differently when quoted.

$@ vs $*

Two flavors of "all arguments":

bash
"$@"      # each argument as a separate word: "$1" "$2" "$3" ...
"$*"      # all arguments joined into one string: "$1 $2 $3"

Almost always you want "$@". It preserves argument boundaries, so an argument containing spaces stays as one argument.

bash
./deploy.sh "monthly report.pdf" backup.tgz

# inside deploy.sh:
for f in "$@"; do echo "$f"; done
# monthly report.pdf
# backup.tgz

for f in "$*"; do echo "$f"; done
# monthly report.pdf backup.tgz    (one line, wrong for iteration)

Rule: use "$@" (with the double quotes) any time you iterate or forward arguments.

shift

shift drops $1 and shifts everything down. $2 becomes $1, $3 becomes $2, and $# decreases by one.

bash
first=$1
shift          # now $1 is what was $2
second=$1

Useful when you want to consume a "leading" argument and hand the rest off to another command:

bash
action=$1
shift
case $action in
  deploy)  ./deploy.sh "$@" ;;
  rollback) ./rollback.sh "$@" ;;
esac

The idiomatic loop

bash
for arg in "$@"; do
  echo "processing $arg"
done

Each iteration binds arg to one argument. Handles spaces correctly because of "$@".

Spin up a fresh environment and practice live.
linux-devops-basic · fresh machine · ready in under a minute