3. Using case statements

3.1. Simplified conditions

Nested if statements might be nice, but as soon as you are confronted with a couple of different possible actions to take, they tend to confuse. For the more complex conditionals, use the case syntax:

case EXPRESSION in CASE1) COMMAND-LIST;; CASE2) COMMAND-LIST;; ... CASEN) COMMAND-LIST;; esac

Each case is an expression matching a pattern. The commands in the COMMAND-LIST for the first match are executed. The | symbol is used for separating multiple patterns, and the ) operator terminates a pattern list. Each case plus its according commands are called a clause. Each clause must be terminated with ;;. Each case statement is ended with the esac statement.

In the example, we demonstrate use of cases for sending a more selective warning message with the disktest.sh script:

anny ~/testdir> cat disktest.sh
#!/bin/bash

# This script does a very simple test for checking disk space.

space=`df -h | awk '{print $5}' | grep % | grep -v Use | sort -n | tail -1 | cut -d "%" -f1 -`

case $space in
[1-6]*)
  Message="All is quiet."
  ;;
[7-8]*)
  Message="Start thinking about cleaning out some stuff.  There's a partition that is $space % full."
  ;;
9[1-8])
  Message="Better hurry with that new disk...  One partition is $space % full."
  ;;
99)
  Message="I'm drowning here!  There's a partition at $space %!"
  ;;
*)
  Message="I seem to be running with an nonexistent amount of disk space..."
  ;;
esac

echo $Message | mail -s "disk report `date`" anny

anny ~/testdir>
You have new mail.

anny ~/testdir> tail -16 /var/spool/mail/anny
From anny@octarine Tue Jan 14 22:10:47 2003
Return-Path: <anny@octarine>
Received: from octarine (localhost [127.0.0.1])
        by octarine (8.12.5/8.12.5) with ESMTP id h0ELAlBG020414
        for <anny@octarine>; Tue, 14 Jan 2003 22:10:47 +0100
Received: (from anny@localhost)
        by octarine (8.12.5/8.12.5/Submit) id h0ELAltn020413
        for anny; Tue, 14 Jan 2003 22:10:47 +0100
Date: Tue, 14 Jan 2003 22:10:47 +0100
From: Anny <anny@octarine>
Message-Id: <200301142110.h0ELAltn020413@octarine>
To: anny@octarine
Subject: disk report Tue Jan 14 22:10:47 CET 2003

Start thinking about cleaning out some stuff.  There's a partition that is 87 % full.

anny ~/testdir>

Of course you could have opened your mail program to check the results; this is just to demonstrate that the script sends a decent mail with To:, Subject: and From: header lines.

Many more examples using case statements can be found in your system's init script directory. The startup scripts use start and stop cases to run or stop system processes. A theoretical example can be found in the next section.

3.2. Initscript example

Initscripts often make use of case statements for starting, stopping and querying system services. This is an excerpt of the script that starts Anacron, a daemon that runs commands periodically with a frequency specified in days.

case "$1" in
        start)
            start
            ;;
         
        stop)
            stop
            ;;
         
        status)
            status anacron
            ;;
        restart)
            stop
            start
            ;;
        condrestart)
            if test "x`pidof anacron`" != x; then
                stop
                start
            fi
            ;;
         
        *)
            echo $"Usage: $0 {start|stop|restart|condrestart|status}"
            exit 1
 
esac

The tasks to execute in each case, such as stopping and starting the daemon, are defined in functions, which are partially sourced from the /etc/rc.d/init.d/functions file. See Chapter 11, Functions for more explanation.