对于这类问题,有一个小技巧可以帮助调试。请在脚本顶部添加以下代码:
export PS4="\$LINENO: "
set -xv
set -xv
会在每行执行之前打印出该行内容,然后在shell插值变量等操作后再次打印该行内容。
$PS4
是由
set -xv
使用的提示符。这将打印出shell脚本执行的行号。您将能够跟踪发生了什么以及可能存在的问题。
以下是一个测试脚本示例:
#! /bin/bash
export PS4="\$LINENO: "
set -xv
FILE1="${@:$OPTIND:1}"
if [ ! -e "$FILE1" ]
then
echo "requested file doesn't exist" >&2
exit 1
else
echo "Found File $FILE1"
fi
当我运行它时,我得到了以下结果:
$ ./test.sh .profile
FILE1="${@:$OPTIND:1}"
6: FILE1=.profile
if [ ! -e "$FILE1" ]
then
echo "requested file doesn't exist" >&2
exit 1
else
echo "Found File $FILE1"
fi
7: [ ! -e .profile ]
12: echo 'Found File .profile'
Found File .profile
在这里,我可以看到我将
$FILE1
设置为
.profile
,而我的脚本理解了
${@:$OPTIND:1}
。最好的是,它适用于所有的Shell,甚至是最初的Bourne Shell。这意味着,如果你认为你正在运行Bash,但实际上不是,你就会看到你的脚本失败的地方,并且可能会修复问题。
我怀疑你可能没有在Bash中运行你的脚本。你是否在顶部放置了
#! /bin/bash
?
script.sh [-g] [-p] [-r FUNCTION_ID|-d FUNCTION_ID] FILE
你可能想使用
getopts
来解析你的参数:
#! /bin/bash
USAGE=" Usage:
script.sh [-g] [-p] [-r FUNCTION_ID|-d FUNCTION_ID] FILE
"
while getopts gpr:d: option
do
case $option in
g) g_opt=1;;
p) p_opt=1;;
r) rfunction_id="$OPTARG";;
d) dfunction_id="$OPTARG";;
[?])
echo "Invalid Usage" 1>&2
echo "$USAGE" 1>&2
exit 2
;;
esac
done
if [[ -n $rfunction_id && -n $dfunction_id ]]
then
echo "Invalid Usage: You can't specify both -r and -d" 1>&2
echo "$USAGE" >2&
exit 2
fi
shift $(($OPTIND - 1))
[[ -n $g_opt ]] && echo "-g was set"
[[ -n $p_opt ]] && echo "-p was set"
[[ -n $rfunction_id ]] && echo "-r was set to $rfunction_id"
[[ -n $dfunction_id ]] && echo "-d was set to $dfunction_id"
[[ -n $1 ]] && echo "File is $1"
FILE1="${@:$OPTIND:1}
是否正确。 - loentarls
命令时,你能清楚地看到什么?问题在于你期望"${@:$OPTIND:1}"
包含一个有效的文件名,但实际上它包含了一个空字符串(或未设置)。显然,文件名为空字符串的文件是不存在的。你需要弄清楚为什么"${@:$OPTIND:1}"
没有包含你期望的值,并且你没有给出足够的信息来帮助我们解决这个问题。 - Keith Thompson