Script foundations

Read positional arguments

Accept a required path argument, show usage, and distinguish the script name from user values.

10 minute lesson

~~~

When you run ./check-dir /var/www, Bash stores the script name in $0 and arguments in $1, $2, and so on. $# reports how many arguments were supplied. These are the positional parameters, and they are how a script receives input without prompting anyone.

Require an argument

A script that needs input should check for it up front and explain itself when the caller gets it wrong. Create check-dir:

#!/usr/bin/env bash

if (( $# != 1 )); then
  printf 'usage: %s DIRECTORY\n' "$0" >&2
  exit 2
fi

directory=$1
printf 'checking %s\n' "$directory"

(( ... )) is arithmetic evaluation, the natural way to compare numbers like $#. The usage message goes to standard error with >&2, not standard output — error text must never mix with real output that another program might consume. Status 2 is the conventional “you called me wrong” code; grep and many other tools use it the same way.

Copying $1 into a named variable is a small kindness to future readers. Twenty lines down, "$directory" explains itself; "$1" doesn’t.

Verify all three cases

Run it with zero, one, and two arguments:

./check-dir
# usage: ./check-dir DIRECTORY

./check-dir /var/www
# checking /var/www

./check-dir /var/www /tmp
# usage: ./check-dir DIRECTORY

Check the status too: echo $? prints 2 after the invalid calls and 0 after the good one. Invalid usage should print to standard error and return status 2 every time, because schedulers and other scripts act on the number, not the text.

Count is not meaning

The realistic mistake is stopping here. One argument can still name a missing or unsafe path:

if [[ ! -d $directory ]]; then
  printf '%s is not a directory\n' "$directory" >&2
  exit 1
fi

Validate meaning after count. A script that accepts any string as its “log directory” and marches on will fail later, somewhere far less obvious than line three.

One more parameter worth knowing now: "$@" expands to all arguments, each preserved as its own word. We put it to work in the lesson on loops.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →