Skip to main content

3. Positional parameters

  1. The shell provides a set of variables called positional parameters that contain the individual words on the command line.

    Let's test them with a simple script:

    posit-param.sh
    #!/bin/bash

    # posit-param: script to view command line parameters

    echo "
    \$0 = $0
    \$1 = $1
    \$2 = $2
    \$3 = $3
    \$4 = $4
    \$5 = $5
    \$6 = $6
    \$7 = $7
    \$8 = $8
    \$9 = $9
    Number of arguments: $#
    "
    vim posit-param.sh
    ./posit-param.sh
    $(pwd)/posit-param.sh

    Notice that $0 contains th first word of the command, which is the name and path of the command itself.

    ./posit-param.sh a b c d

    The special variable $# contains the number of arguments.

    If we need to use more than 9 arguments, then we can use ${10}, ${11} etc. to access them (with curly braces).

  2. The shift command causes all the parameters to "move down one" each time it is executed.

    posit-param2.sh
    #!/bin/bash

    # posit-param2: script to display all arguments

    count=1

    while [[ $# -gt 0 ]]; do
    echo "Argument $count = $1"
    count=$((count + 1))
    shift
    done
    vim posit-param2.sh

    In this example there is a loop that evaluates the number of arguments remaining and continues as long as there is at least one.

    ./posit-param2.sh a b c d
    ./posit-param2.sh a b c d e f g
  3. Here is another example:

    file-info.sh
    #!/bin/bash

    # file-info: simple file information program

    PROGNAME="$(basename "$0")"

    if [[ -e "$1" ]]; then
    echo -e "\nFile Type:"
    file "$1"
    echo -e "\nFile Status:"
    stat "$1"
    else
    echo "$PROGNAME: usage: $PROGNAME file" >&2
    exit 1
    fi
    vim file-info.sh

    This program displays the file type (determined by the file command) and the file status (from the stat command) of a specified file.

    It checks the first argument, and if it does not exist, exits with an error message that shows how to use this script.

    The command basename gets only the name of the file (discarding the path).

    ./file-info.sh
    ./file-info.sh posit-param2.sh
    ./file-info.sh .
    ./file-info.sh xyz
  4. Positional parameters can be used with functions as well.

    file-info-fun.sh
    #!/bin/bash

    file_info () {
    if [[ -e "$1" ]]; then
    echo -e "\nFile Type:"
    file "$1"
    echo -e "\nFile Status:"
    stat "$1"
    else
    local PROGNAME="$(basename "$0")"
    echo "$PROGNAME: usage: $FUNCNAME file" >&2
    return 1
    fi
    }

    echo -e '\nCalling file_info without args: file_info'
    file_info

    FILE=$0
    echo -e '\nCalling file_info with an argument: file_info $FILE'
    file_info $FILE

    vim file-info-fun.sh

    Notice that $0 always contains the full pathname of the first item on the command line (i.e., the name of the program), even inside a function.

    Notice also that FUNCNAME is a variable that always contains the name of the current function.

    ./file-info-fun.sh
  5. The shell provides two special variables that contain the list of all the positional parameters. They are $* and $@. Let's try an example that shows their differences:

    posit-param3.sh
    #!/bin/bash

    # posit-params3: script to demonstrate $* and $@

    print_params () {
    echo "\$1 = $1"
    echo "\$2 = $2"
    echo "\$3 = $3"
    echo "\$4 = $4"
    echo
    }

    pass_params () {
    echo '-- $* --' ; print_params $*
    echo '-- "$*" --' ; print_params "$*"
    echo '-- $@ --' ; print_params $@
    echo '-- "$@" --' ; print_params "$@"
    }

    pass_params "word" "words with spaces"
    vim posit-param3.sh
    ./posit-param3.sh

    You see that both $* and $@ give 4 parameters. "$*" gives a single parameter, and "$@" gives back the two original parameters. This happens because $* is a string list of all the parameters, while $@ is an array of all the parameters.

    Anyway, the most useful construct seems to be "$@" because it preserves the original list of the parameters, and this is what we want in most of the cases.

Loading asciinema cast...