Bash脚本函数调用错误



我正在编写我的第一个Bash脚本,并且在函数调用中遇到语法问题。

具体来说,我想这样调用我的脚本:

sh myscript.sh -d=<abc>

其中<abc>为固定父目录(~/app/dropzone)下的特定目录的名称。如果子<abc>目录不存在,我希望脚本在进入该目录之前创建它。如果用户根本不使用-d参数调用脚本,我希望脚本存在,并附带一个简单的用法消息。以下是我目前为止对脚本的最佳尝试:

#!/bin/bash
dropzone="~/app/dropzone"
# If the directory the script user specified exists, overwrite dropzone value with full path
# to directory. If the directory doesn't exist, first create it. If user failed to specify
# -d=<someDirName>, exit the script with a usage statement.
validate_args() {
    args=$(getopt d: "$*")
    set -- $args
    dir=$2
    if [ "$dir" ]
    then
        if [ ! -d "${dropzone}/targets/$dir" ]
        then
            mkdir ${dropzone}/targets/$dir
        fi
        dropzone=${dropzone}/targets/$dir
    else
        usage
    fi
}
usage() {
    echo "Usage: $0" >&2
    exit 1
}
# Validate script arguments.
validate_args $1
# Go to the dropzone directory.
cd dropzone
echo "Arrived at dropzone $dropzone."
# The script will now do other stuff, now that we're in the "dropzone".
# ...etc.

当我尝试运行这个时,我得到以下错误:

myUser@myMachine:~/app/scripts$ sh myscript.sh -dyoyo
mkdir: cannot create directory `/home/myUser/app/dropzone/targets/yoyo': No such file or directory
myscript.sh: 33: cd: can't cd to dropzone
Arrived at dropzone /home/myUser/app/dropzone/targets/yoyo.

我哪里错了,我的一般方法是正确的吗?提前感谢!

将函数定义移动到脚本的顶部(hashbang下面)。bash反对对validate_args的未定义调用(在那个点)。usage的定义应该先于validate_args的定义。

if测试"["one_answers"]"也应该有空格。

    if [ -d "$dropzone/targets/$1" ]

选项d的getopt测试应为-:

    if [ "$(getopt d "$1")" ]

这是一个版本的validate_args为我工作。我还必须更改在我的shell上的拖放区~在mkdir命令中不会展开。

dropzone="/home/suspectus/app/dropzone"
validate_args() {
    args=$(getopt d: "$*")
    set -- $args
    dir=$2
    if [ "$dir" ]
    then
        if [ ! -d "${dropzone}/targets/$dir" ]
        then
            mkdir ${dropzone}/targets/$dir
        fi
        dropzone=${dropzone}/targets/$dir
    else
        usage
    fi
}

使用$*作为参数传递所有参数-:

  validate_args $*

最后像这样调用脚本以便getopt正确解析-:

  myscript.sh -d dir_name

在调用时,函数与命令是无法区分的——所以不要使用括号:

validate_args($1)  # Wrong
validate_args $1   # Right

此外,正如suspect在他的回答中指出的,函数必须在调用之前定义。您可以通过以下脚本看到:

usage
usage()
{
    echo "Usage: $0" >&2
    exit 1
}

将报告usage: command not found,假设您没有一个名为usage的命令或函数可用。将调用放在函数定义之后,它将正常工作。


您选择的接口不是标准的Unix命令调用约定。你通常会使用:

dropzone -d subdir

而不是

dropzone -d=subdir

然而,我们可以处理你选择的接口(但不使用getopts,内置的命令解释器,也可能不使用GNU getopt,当然也不使用getopt,因为你试图这样做)。以下是支持-d=subdir的可用代码:#!/bin/bash

dropzone="$HOME/app/dropzone/targets"
validate_args()
{
    case "$1" in
    (-d=*)  dropzone="$dropzone/${1#-d=}"; mkdir -p $dropzone;;
    (*)     usage;;
    esac
}
usage()
{
    echo "Usage: $0 -d=dropzone" >&2
    exit 1
}
# Validate script arguments.
validate_args $1
# Go to the dropzone directory.
cd $dropzone || exit 1
echo "Arrived at dropzone $dropzone."
# The script will now do other stuff, now that we're in the "dropzone".
# ...etc.

注意cd $dropzone || exit 1;如果cd失败,您肯定不希望在错误的目录中继续。

使用getopts内置命令解释器:

#!/bin/bash
dropzone="$HOME/app/dropzone/targets"
usage()
{
    echo "Usage: $0 -d dropzone" >&2
    exit 1
}
while getopts d: opt
do
    case "$opt" in
    (d) dropzone="$dropzone/$OPTARG"; mkdir -p $dropzone;;
    (*) usage;;
    esac
done
shift $(($OPTIND - 1))
# Go to the dropzone directory.
cd $dropzone || exit 1
echo "Arrived at dropzone $dropzone."
# The script will now do other stuff, now that we're in the "dropzone".
# ...etc.

最新更新