Navigation überspringen

Harald Markus Wirth


Seiteninhalt:

Shell script with getopts example

#!/bin/bash
###############################################################################
PROGRAM_NAME="bash script template"
SCRIPT_VERSION="0.1a"
###############################################################################
# copy(l)eft 2019 http://harald.ist.org/
###############################################################################

DEBUG=false

###############################################################################
# INIT
###############################################################################

trap cleanup SIGINT                         # Handles aborting with ^C

# Colored output
TEXT_UNDERLINE="$(tput smul)"
TEXT_endUNDERLINE="$(tput rmul)"
TEXT_STANDOUT="$(tput smso)"                # Inverse colors on my terminal
TEXT_endSTANDOUT="$(tput rmso)"
TEXT_DIM="$(tput dim)"
TEXT_BOLD="$(tput bold)"
TEXT_BLINK="$(tput blink)"
TEXT_REVERSE="$(tput rev)"
TEXT_RED="$(tput setaf 1)"
TEXT_GREEN="$(tput setaf 2)"
TEXT_YELLOW="$(tput setaf 3)"
TEXT_BLUE="$(tput setaf 4)"
TEXT_MAGENTA="$(tput setaf 5)"
TEXT_CYAN="$(tput setaf 6)"
TEXT_WHITE="$(tput setaf 7)"
TEXT_RESET="$(tput sgr0)"

ESC=$(echo -e "\e")

SCRIPT_NAME=$(basename $0)

#
# Execution continues at bottom of script near "SCRIPT ENTRY POINT"
#


###############################################################################
# HELPERS
###############################################################################

debug() {
        ($DEBUG) && echo -e "Debug: $1"
}

error() {
        exit_code=$1
        shift                           # Remove $1 from argument list
        echo "Error: $@"                # Echo the rest to ERROUT
        exit $exit_code
}


function do_as_su()
{
        # Command needs to be executed as root
        # do_as_su <command line>

        if [ "$(whoami)" = "root" ] ; then
                $@
        else
                DECL=$(declare -f $1)
                cmd=$1
                shift
                params=$@
                sudo bash -c "$DECL; $cmd $params"
        fi
}


###############################################################################
# CLEAN UP
###############################################################################

cleanup() {
        # Clean up, when ^C was pressed

        echo "Aborting, cleaning up."
}


###############################################################################
# DISPLAY HELP
###############################################################################

display_help() {
        echo "${TEXT_BOLD}${PROGRAM_NAME} ${TEXT_RESET}v${SCRIPT_VERSION}"
        echo "Usage: $SCRIPT_NAME [-h] [-s|-v] [-f file] [-V var=val] [item(s)]"
        ($VERBOSE_HELP) && cat << EOF

Switches:
        -f file,                Name of file
        -F=file, --file=file
        -h, --help              Display verbose help and terminate execution
        -s, --silent            Be silent
        -v, --verbose           Be extra verbose about what is going on
        -V name=value,          Change a preset value, names are case sensitive
        --var name=value

Objects (Items)
        obj1, obj2
        item1, item2, item3

Examples:
        $SCRIPT_NAME -f test.out
        $SCRIPT_NAME --file=test.out
        $SCRIPT_NAME -v FILE_NAME=test.out
        $SCRIPT_NAME item1

EOF
}

###############################################################################
# MAIN FUNCTION
###############################################################################
# getopts can't handle "--long-opts", so all long option names have to be
# converted into the short version, before we can process them. Since we can't
# manipulate the $@ variable, the substitution is done outside, see
# SCRIPT ENTRY POINT.

known_items()
{        # Finds $1 in list, items may contain white space
        grep -F -q -x "$1" << EOF 2> /dev/null
item1
item2
item3
EOF
        ### [ $? -ne 0 ] && error 1 \"$1\" not in items.
}


known_objects()
{        # Finds $1 in list, no white space allowed
        echo "$KNOWN_OBJECTS" | grep -F -q -w "$1"
}


main() {
        # Set initial state for command line switches
        VERBOSITY=1                     # Default verbosity
        VERBOSE_HELP=false              # Full help when --help is given
        FILE_NAME=default.out           # Test parameter for -f and -v
        KNOWN_OBJECTS="obj1 obj2"       # Test objects

        while getopts $GETOPTS_LIST param ; do
                debug "OPTARG='$OPTARG'"
                debug "OPTIND=$OPTIND"
                debug "param=$param"

                case $param in
                f)        FILE_NAME="$OPTARG" ;;
                F)        eval "FILE_NAME$OPTARG" ;;
                h)        VERBOSE_HELP=true ; display_help ; exit 0 ;;
                s)        VERBOSITY=0 ;;
                v)        VERBOSITY=2 ;;
                V)        eval $OPTARG 2>/dev/null ;;
                \?)        error 2 "Unknown option \"-$OPTARG\"." ;;
                :)        error 3 "Option \"-$OPTARG\" needs an argument." ;;
                *)        error -1 "You should never read this." ;;
                esac
        done

        [ $OPTIND -eq 1 ] && display_help ; exit 0   # Show short help

        # Remaining arguments are objects/items
        shift $(( OPTIND - 1 ))   # Remove switches from stack
        for argument in $@ ; do
                known_items   "$argument" && echo "Found item '$argument'"
                known_objects "$argument" && echo "Found object '$argument'"
        done

        [ $VERBOSITY -ge 1 ] && echo "FILE_NAME='$FILE_NAME'"
        [ $VERBOSITY -ge 2 ] && echo "Done."

        exit 0
}


###############################################################################
# SCRIPT ENTRY POINT (Execution starts here) Before we can process the command
# line arguments with getopts, we have to replace --long-opts with their short
# counterparts, and create a modified parameter list to pass on to  main()
###############################################################################

# List of long switches and their short counterparts: The first character is
# the short switch for the long one. Like -V and --list-vars"

GETOPTS_LIST=':f:F:hsuvV:'
SWITCH_ALIASES="Ffile hhelp ssilent vverbose Vvar"

long_to_short() {
        argument=$1
        for alias in $SWITCH_ALIASES ; do
                short=-${alias:0:1}
                long=${alias/ *}
                long=--${long:1}
                argument=${argument//$long/$short}
        done
        ARGUMENTS="$ARGUMENTS $argument"
}

ARGUMENTS="" ; for A in "$@" ; do long_to_short $A ; done ; main $ARGUMENTS

#EOF


Content Management:

μCMS α1.6