以下 shell 脚本采用参数列表,将 Unix 路径转换为 WINE/Windows 路径,并在 WINE 下调用给定的可执行文件。
#! /bin/sh
if [ "${1+set}" != "set" ]
then
echo "Usage; winewrap EXEC [ARGS...]"
exit 1
fi
EXEC="$1"
shift
ARGS=""
for p in "$@";
do
if [ -e "$p" ]
then
p=$(winepath -w $p)
fi
ARGS="$ARGS '$p'"
done
CMD="wine '$EXEC' $ARGS"
echo $CMD
$CMD
但是,命令行参数的引用有问题。
$ winewrap '/home/chris/.wine/drive_c/Program Files/Microsoft Research/Z3-1.3.6/bin/z3.exe' -smt /tmp/smtlib3cee8b.smt
Executing: wine '/home/chris/.wine/drive_c/Program Files/Microsoft Research/Z3-1.3.6/bin/z3.exe' '-smt' 'Z: mp\smtlib3cee8b.smt'
wine: cannot find ''/home/chris/.wine/drive_c/Program'
注意:
- 可执行文件的路径在第一个空格处被截断,即使它是单引号。
- 最后一个路径中的文字“\t”正在转换为制表符。
显然,引用并没有按照我预期的方式被 shell 解析。我怎样才能避免这些错误?
编辑: "\t" 正在通过两个间接级别进行扩展:首先,"$p"
(and/or "$ARGS"
) 正在扩展为Z:\tmp\smtlib3cee8b.smt
; 然后,\t
正在扩展为制表符。这(似乎)相当于
Y='y\ty'
Z="z${Y}z"
echo $Z
产生
zy\tyz
而不是
zy yz
更新:eval "$CMD"
成功了。" \t
" 问题似乎是 echo 的错误:“如果第一个操作数是 -n,或者任何操作数包含反斜杠 ('\') 字符,则结果是实现定义的。” (POSIX 规范echo
)