繁体   English   中英

Bash 脚本检查命令行参数

[英]Bash script checking command line parameters

I am still on the learning path of bash, shell, Linux, regex etc. Today I share this bash shell script that I have programmed and that I want to use as a "module" in future scripts. 它彻底测试了一组命令行参数的有效性。 我想请有经验的专家就如何在语法、不同方法或替代命令方面更好地归档内容提供建议和意见。 我尝试了很多不同的方法,但我无法弄清楚。 特别是我不喜欢“案例”结构。 我宁愿定义一组选项字母,例如 'cmds=(hogam)',然后使用 'for c in "${cmds[@]}"; 做'。 但这导致了我必须使用动态变量名的问题,而我无法弄清楚。 另一个问题是,我可以将 boolean 分配为“真”,但我不能用“a=.a”之类的东西来否定它。 等等任何建议都非常欢迎!

#!/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

正如@Shawn 在评论中所建议的那样,使用“getopts”,解析将变为:

# 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM