Bash скрипт проверки параметров командной строки - PullRequest
0 голосов
/ 04 апреля 2020

Я все еще на пути обучения bash, shell, Linux, regex et c. Сегодня я делюсь этим bash сценарием оболочки, который я запрограммировал и который хочу использовать в качестве «модуля» в будущих сценариях. Он тщательно проверяет правильность набора параметров командной строки. Я хотел бы попросить опытных адептов за советом и комментариями о том, как лучше архивировать вещи с точки зрения синтаксиса, различных подходов или альтернативных команд. Было много того, что я пробовал по-другому, но я не мог понять это. Особенно мне не нравятся структуры case. Я бы лучше определил набор букв опций, например, «cmds = (hogam)», а затем l oop через «for c в« $ {cmds [@]} »; делать'. Но это приводит к проблеме, что мне придется использовать динамические c имена переменных, и я не мог понять это. Другая проблема заключается в том, что я могу присвоить логическое значение «истина», но я не могу отрицать его с помощью чего-то вроде «a =! A». Et c. Любые предложения очень приветствуются!

#!/bin/bash

# Usage: -p <path> -g <group> -o <owner> -m <mask> -h (help)

# Extensive option and parameter check:

expecting_option=true # alternatingly expecting option switch and parameter on command line

for i do # loop $i trough all parameters

    # display help:
    if [ $i = "-h" ]; then
        echo "Usage:"
        echo "-p <path> (default .)"
        echo "-o <owner>"
        echo "-g <group>"
        echo "-m <permission mask> (000 - 777)"
        exit
    fi;

    if [ "$expecting_option" = true ]; then # next arg supposed to be an option

        if [[ "$i" =~ ^(.)(.*?)(.*?)$ ]]; then # retrieve up to 3 single characters

            # Does it begin with '-' ?
            if [ ${BASH_REMATCH[1]} != "-" ]; then
                echo "ERROR: Option to begin with '-' expected at '"$i"'" >&2
                exit
            fi

            # only one letter length for options
            if [ -n "${BASH_REMATCH[3]}" ]; then
                echo "ERROR: Invalid option '"$i"'. Use -h for help" >&2
                exit
            fi

            switch=${BASH_REMATCH[2]} # save the current option switch

            # has this option already been set?
            # is option valid?
            case $switch in
                o)  if [ $o ]; then
                        echo 'ERROR: duplicate option: -o' >&2
                        exit
                    fi;;
                g)  if [ $g ]; then
                        echo 'ERROR: duplicate option: -g' >&2
                        exit
                    fi;;
                m)  if [ $m ]; then
                        echo 'ERROR: duplicate option: -m' >&2
                        exit
                    fi;;
                p)  if [ $p ]; then
                        echo 'ERROR: duplicate option: -p' >&2
                        exit
                    fi;;
                *)  echo "ERROR: Invalid option '"$i"'. Use -h for help" >&2
                    exit;;
            esac
        fi

        # next arg supposed to be the parameter
        expecting_option=!true # it's not true, so it works. But is it 'false'?

    else # this is supposed to be a parameter for the previous option switch

        if [[ "$i" =~ ^\- ]]; then # starts with '-' ?
            echo "ERROR: Parameter for "$switch" missing." >&2
            exit
        fi

        case $switch in
            o)  # check if designated owner exists (=0):
                if ! [ $(id -u "$i" > /dev/null 2>&1; echo $?) -eq 0 ]; then
                    echo "ERROR: user '"$i"' does not exist." >&2
                    exit
                fi
                o="$i";;
            g)  # check if designated group exists:
                if [ -z $(getent group "$i") ]; then
                    echo "ERROR: group '"$i"' does not exist." >&2
                    exit
                fi
                g="$i";;
            m)  if ! [[ $i =~ ^[0-7][0-7][0-7]$ ]]; then
                    echo "ERROR: Invalid right mask '"$i"'" >&2
                    exit
                fi
                m="$i";;
            p)  # check if path exists
                if ! [ -d "${i}" ]; then
                    echo "ERROR: Directory '"$i"' not found." >&2
                    exit
                fi
                p="$i";;
        esac

        expecting_option=true
    fi

done

# last arg must be a parameter:
if [ "$expecting_option" != true ]; then
    echo "ERROR: Parameter for "$switch" missing." >&2
    exit
fi

# at least o, g or m must be specified:

if ! [ $g ] && ! [ $o ] && ! [ $m ] ; then  
# this didn't work:  if ! [ [ $g ] || [ $o ] || [ $m ] ] ; then 
    echo "Nothing to do. Specify at least owner, group or mask. Use -h for help."
    exit
fi

# defaults: path = . owner = no change  group = no change  mask = no change
# set defaults:
[[ -z $p ]] && p="."

# All necessary options are given and checked:
# p defaults to . otherwise valid path
# if o is given, than the user exists
# if g is given, than the group exists
# if m is given, than the mask is valid
# at least one of o,g or m are given
# no option dupes
# no missing parameters

# ok, now let's do something:

# set group:owner + mask of whole directory tree:
if  [ $g ] || [ $o ] ; then
    [[ -n $g ]] && g=":"$g # use chown's column only if group change required, with or without owner
    sudo find $p -type f -exec chown $o$g {} + &&
    sudo find $p -type d -exec chown $o$g {} + 
fi
if [ $m ]; then
    sudo find $p -type f -exec chmod $m {} + &&
    sudo find $p -type d -exec chmod $m {} +
fi

1 Ответ

2 голосов
/ 04 апреля 2020

С 'getopts', как предложено @Shawn в комментарии, синтаксический анализ станет:

# Default values for options
g=
o=
P=.
m=
while getopts g:o:p:m: opt ; do
    case "$opt" in
        g) g=$OPTARG ;;
        o) o=$OPTARG ;;
        p) p=$OPTARG ;;
        m) m=$OPTARG ;;
        # Abort on illgal option
        *) exit 2 ;;
    esac
done
shift $((OPTIND-1))

# Rest of code goes here
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...