This article covers advanced usage of variables in shell scripts, including argument parsing and variable access.

1. Defining Functions in Shell

Besides its built-in commands, Shell also supports user-defined functions. The benefit is code reuse and easier maintenance.

[function] fun_name[()]
{
    echo $0
    echo $1
    [return x]
}
  • A function name must follow the same rules as a variable name.
  • The function keyword before the name is optional, and the () after the name is optional, but {} is required.
  • The final return x is optional; if omitted, the return value of the function is the exit status of its last command, and a function’s return value can only be a number.
  • A function can take any number of arguments.

Inside the function body, access the arguments as $0, $2, … $n. You can also use $@ and $* to represent all of the arguments.

fun_name arg1 arg2 arg3

2. Parsing Passed Arguments

A shell script can receive arguments when it runs, letting different arguments produce different output.

bash xxx.sh arg1 arg2
VariableMeaning
$nAn argument passed to the script or function, where n is a number counting from zero; the first argument is $1
$0The filename of the current script — the “zeroth” argument of a shell script
$#The number of arguments passed to the script or function
$*All arguments passed to the script or function
$@All arguments passed to the script or function
$?The exit status of the last command, or a function’s return value
$$The process ID of the current shell — for a shell script, the process ID the script is running under

Both $* and $@ represent all arguments passed to a function or script.

  • When not enclosed in double quotes (" "), both output all arguments as "$1" "$2" … "$n".
  • When enclosed in double quotes (" "):
    • "$*" treats all the arguments as a single whole, outputting them as "$1 $2 … $n".
    • "$@" keeps each argument separate, outputting them as "$1" "$2""$n".

Argument parsing has no fixed order and no distinction between positional and optional arguments the way Python’s argparse has — the result is simply a list, and all argument parsing amounts to matching against that list. A variable with a leading - is treated differently from one without.

  1. Checking whether the command received any arguments
if [ $# -lt 1 ];
then
echo "no arguments"
else
echo "has $# args"
fi
  1. Checking whether the command received a specific argument
j="-x"
for i in $@;
do
if [ $i = $j ];
then
echo "has $j"
fi
done

3. Including Files

A common need is defining a function in one file and calling it from another file. This is where source or . comes in.

# funa in a.sh
funa {
     echo "funa"
}

To call a.sh’s funa from b.sh:

. a.sh
funa

4. Summary

This article covered how functions are defined and used in Shell.