Americas

  • United States
sandra_henrystocker
Unix Dweeb

Verifying bash script arguments

How-To
Apr 06, 20235 mins
Linux

Check out how you can ensure that proper arguments are passed to your bash scripts.

Many bash scripts use arguments to control the commands that they will run and the information that will be provided to the people running them. This post examines a number of ways that you can verify arguments when you prepare a script and want to make sure that it will do just what you intend it to do – even when someone running it makes a mistake.

Displaying the script name, etc.

To display the name of a script when it’s run, use a command like echo $0. While anyone running a script will undoubtedly know what script they just invoked, using the script name in a usage command can help remind them what command and arguments they should be providing.

Script names can be displayed along with the expected arguments like this:

echo Usage: $0 month year

The $0 argument represents the name of the script.

Usage statements are often displayed when a user doesn’t enter the proper arguments to run a script. A usage statement will remind people what is expected – especially when they run the script very infrequently.

Checking the number of arguments provided

To display the number of arguments provided by the user, you can use a command like echo $#. That $# represents the number of arguments provided by the user. Your script can verify that it is what the script requires. Here’s an example:

if [ $# != 2 ]; then
  echo $0 username date (e.g., 12/01/2023)

The code above asks if the number of arguments provided is not equal to two. You can also use commands like these;

if [ $# == 2]        # if number of arguments equals 2
if [ $# -lt 3 ]      # if number of arguments is less than 3
if [ $# -gt 4 ]      # if number of arguments is more than 4

The == (equals), lt (less than) and gt (greater than) comparisons are often used to verify that the correct number of arguments were provided by the person running the script.

Verifying the arguments

If a script is going to work with a file, you might want to check that the specified file exists before the script runs a command that is meant to process or examine it. For example:

filename=$1     # first argument should be filename
if [ ! -e $filename ]; then
  echo “No such file: $filename”
fi

The ! -e part of the command above tests “if there is no file with the name”. You can also have a script verify file permissions. For example, to check whether the person running the script can read, write or execute a file, you can use commands such as these:

if [ ! -r $1 ]; then
  echo cannot read $1
fi
if [ ! -x $1 ]; then
  echo cannot run $1
fi
if [ ! -w $1 ]; then
  echo cannot write to $1
fi

The person running the script might see something like this:

$ countlines thatfile
cannot read thatfile

Verifying argument types

There are a number of ways that you can verify the type of arguments provided to a script. For example, you can check whether an argument is a number or a string of letters. You can even check if the arguments include a month and a year. Here are some examples of how to do these things:

Check if numeric

The code below ensures the argument provided is a single string of digits. The $re variable sets up the pattern (all digits).

# check if argument is numeric
re='^[0-9]+$'
if ! [[ $2 =~ $re ]] ; then
   echo "error: Not a number"
   exit 2
fi

Check if a string of characters

The code below ensures that the argument is a string of characters. You can elect to check if it contains only lowercase or uppercase letters.

To check if an argument contains only lowercase letters:

# check argument is characters
re='^[a-z]+$'
if ! [[ $1 =~ $re ]] ; then
   echo "error: Not alphabetic"
   exit 3
fi

To check if an argument contains only uppercase letters:

# check argument is characters
re='^[A-Z]+$'
if ! [[ $1 =~ $re ]] ; then
   echo "error: Not alphabetic"
   exit 3
fi

To check if an argument contains only letters (uppercase or lowercase):

# check argument is characters
re='^[a-zA-Z]+$'
if ! [[ $1 =~ $re ]] ; then
   echo "error: Not alphabetic"
   exit 3
fi

NOTE: The order of the letters in the argument provided is unimportant for these tests. The “re” (regular expression) tests simply ensure that the argument provides only characters in the range specified.

Looping through script arguments

The command below will loop through all of the arguments that are provided when a script is run.

# display list of arguments
for arg in "$@"
do
    echo "$arg"
done

The $@ string represents the list of arguments provided. The for command then loops through them, displaying them one at a time.

Checking command-specific syntax

The command shown below will verify that the syntax for a specific command that the script is expected to run – in this case, the cal (calendar) command – is correct. It does this in a very interesting way. It runs the command and sends its output to /dev/null (the “bit bucket”). If the error code returned indicates that the command failed in some way (i.e., the return code is greater than zero), the script tells the user the command failed. Otherwise, it runs the command again, displaying the output expected.

# check if year/month are valid
cal $1 $2 >/dev/null
if [ $? != 0 ]; then          # error encountered
  echo Invalid month and/or year
  exit 4
else
  cal $1 $2
fi

Wrap-up

There are many ways to verify the arguments provided to a script when it is run. This is especially useful when you are preparing scripts that other people – especially less script-savvy people than yourself – will end up running.

sandra_henrystocker
Unix Dweeb

Sandra Henry-Stocker has been administering Unix systems for more than 30 years. She describes herself as "USL" (Unix as a second language) but remembers enough English to write books and buy groceries. She lives in the mountains in Virginia where, when not working with or writing about Unix, she's chasing the bears away from her bird feeders.

The opinions expressed in this blog are those of Sandra Henry-Stocker and do not necessarily represent those of IDG Communications, Inc., its parent, subsidiary or affiliated companies.

More from this author