我正在编写我的第一个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.
我哪里出错了,我的一般方法是否正确?提前谢谢!
答案 0 :(得分:3)
将函数定义移动到脚本的顶部(在hash-bang下面)。 bash
反对未定义(此时)调用validate_args
。 usage
定义应位于validate_args
的定义之前。
if tests“[”和“]”中也应该有间距。
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
答案 1 :(得分:1)
调用时,函数与命令无法区分 - 所以你不要使用括号:
validate_args($1) # Wrong
validate_args $1 # Right
此外,正如suspectus中answer指出的那样,必须在调用函数之前定义函数。你可以用脚本看到这个:
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
的可行代码:
#!/斌/庆典
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.