Scriptvorlage für Bash-Scripts

Die Begründung, warum ich eine Vorlage mache, findet sich an einer anderen Stelle. Hier stelle ich meine Vorlage für Bash vor.

Beschreibung

Die hier vorgestellte Vorlage verwende ich normal für bash. Sie sollte aber eigentlich nahezu genauso für die klassische sh oder die etwas exotischere zsh funktionieren.

Das Script unterstützt nur einfache Parameter mit je einem Zeichen. Zum Beispiel kann mit einem -h folgende Hilfe ausgegeben werden:

Call:   ./template.sh <Optionen> <Parameter>
Template for bash scripts.

The following parameters are optional:
  -h          Print this help and exit the script.
  -x          Parameter.
  -y <VAL>    Another parameter. Default: Default
  -v          Be more verbose. Can be used multiple times.

Parameter und Optionen dürfen hier (im Gegensatz zu der Perl-Scriptvorlage nicht gemischt werden. Ein möglicher Aufruf und die produzierte Ausgabe sieht wie folgt aus:

sh> ./template.sh -v -y abc -vv def
Verbose level: 3
Parameter: def
-x: 0
-y: abc

Vorlage

Aber genug geschrieben. Hier kommt die eigentliche Vorlage. Alles wichtige ist im Script kommentiert. Das ganze Script kann hier heruntergeladen werden.

#!/bin/bash

# Copyright (c) 2014 Christian Mauderer <oss@c-mauderer.de>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

# exit on wrong command and undefined variable
set -e
set -u
# The following one only works for bash. It catches the fail of the first
# command in a pipe. e.g. 'which asdf | true' would fail due to the missing asdf
# command.
set -o pipefail

PARAM1=0
PARAM2="Default"
VERBOSE=0

SCRIPTNAME=$0

# Print a error message and exits with 1
# Arguments:
#   0: message
printerror () {
    echo "ERROR: $1"
    echo ""
    echo "Call with \"${SCRIPTNAME} -h\" for help."
    exit 1
}

# Check if the parameter is a program. Print error and exit if not.
# Arguments:
#   0: program name
test_command () {
    if ! which $1 >/dev/null 2>&1
    then
        printerror "Command \"$1\" not found."
    fi
}

# Print a message depending on verbose level (set in ${VERBOSE}).
# Arguments:
#   0: message will be printed on this level
#   1: message
print_msg () {
    local LEVEL="$1"
    local MSG="$2"

    if [ ${LEVEL} -le ${VERBOSE} ]
    then
        echo "${MSG}"
    fi
}

# Print a help text and exit
# Arguments:
#   n.a.
printhelp () {
    echo ""
    echo "Call:   ${SCRIPTNAME} <options> <parameters>"
    echo "Template for bash scripts. Needs at least one parameter."
    echo ""
    echo "The following parameters are optional:"
    echo "  -h          Print this help and exit the script."
    echo "  -x          Parameter."
    echo "  -y <VAL>    Another parameter. Default: ${PARAM2}"
    echo "  -v          Be more verbose. Can be used multiple times."
    exit 0
}

# The main script

# Read options
while getopts "hxy:v" OPTION
do
    case ${OPTION} in
        h)  printhelp ;;
        x)  PARAM1=1 ;;
        y)  PARAM2=${OPTARG} ;;
        v)  VERBOSE=$((${VERBOSE} + 1)) ;;
        \?) printerror "Unknown option \"-${OPTARG}\"." ;;
        :)  printerror "Option \"-${OPTARG}\" needs an argument." ;;
    esac
done
# Remove the already processed ones
shift $((${OPTIND} - 1))

# Process all parameters without dash
[[ $# -lt 1 ]] && printerror "Needs at least one parameter."
PARAMETER="$1"

# Check commands
# Not necessary in this case. But there is an example:
# test_command "vim"

# Do something
print_msg 1 "Verbose level: ${VERBOSE}"
print_msg 1 "Parameter: ${PARAMETER}"
print_msg 2 "-x: ${PARAM1}"
print_msg 2 "-y: ${PARAM2}"

# vim: set ts=4 sw=4: