我正在编写我的第一个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.