2008-08-30 73 views
3

以下shell脚本获取参数列表,将Unix路径转换为WINE/Windows路径并调用WINE下的给定可执行文件。在shell脚本中引用命令行参数

#! /bin/sh 

if [ "${1+set}" != "set" ] 
then 
    echo "Usage; winewrap EXEC [ARGS...]" 
    exit 1 
fi 

EXEC="$1" 
shift 

ARGS="" 

for p in "[email protected]"; 
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' 

需要注意的是:

  1. 到可执行文件的路径被砍掉的第一空间,即使是单引号。
  2. 最后一个路径中的文字“\ t”正被转换为制表符。

显然,报价并未按照我预期的方式进行分析。我怎样才能避免这些错误?

编辑:“\ t”正在通过两个级别的间接进行扩展:首先,"$p"(和/或"$ARGS")正在扩展为Z:\tmp\smtlib3cee8b.smt;然后,\t正在扩展为制表符。这是(貌似)相当于

Y='y\ty' 
Z="z${Y}z" 
echo $Z 

其产生

zy\tyz 

zy yz 

UPDATE:eval "$CMD"的伎俩。 “\t”问题似乎是echo的错误:“如果第一个操作数是-n,或者任何操作数包含反斜杠('\')字符,则结果将由实现定义。” (POSIX specification of echo

回答

1

我有分配到CMD,你应该在你的脚本的最后一行用

eval $CMD

,而不是仅仅$CMD。这应该解决您的路径中的空间问题,我不知道如何处理“\ t”问题。

0

你可以尝试用\前述的空间,像这样:

/home/chris/.wine/drive_c/Program Files/Microsoft\ Research/Z3-1.3.6/bin/z3.exe 

你也可以做同样的你的\ t问题 - 以\\牛逼更换。

+0

这两个路径都是完全有效的Unix路径*作为脚本*的输入。单引号应该消除逃脱空间的需要。 “\ t”由`winepath`命令自动生成(它将“/ tmp”变为“Z:\ tmp”)。 – 2008-08-30 17:01:24

0

从$ CMD替换最后一行刚刚

酒 '$ EXEC' $ ARGS

你会注意到,该错误是 '' /home/chris/.wine/drive_c/Program”而不是'/home/chris/.wine/drive_c/Program'

单引号没有正确插入,并且字符串被空格分隔。你想

3
  • bash的数组是不可移植,但处理的外壳
  • 参数的个数是$ {#}如果有开头的文件名
  • 糟糕的事情将与你的脚本发生的参数列表的唯一理智的方式在当前目录
  • 如果你的脚本的最后一行刚刚运行的程序,并有退出没有陷阱破折号,你应该Exec的它

考虑到这一点

#! /bin/bash 

# push ARRAY arg1 arg2 ... 
# adds arg1, arg2, ... to the end of ARRAY 
function push() { 
    local ARRAY_NAME="${1}" 
    shift 
    for ARG in "${@}"; do 
     eval "${ARRAY_NAME}[\${#${ARRAY_NAME}[@]}]=\${ARG}" 
    done 
} 

PROG="$(basename -- "${0}")" 

if ((${#} < 1)); then 
    # Error messages should state the program name and go to stderr 
    echo "${PROG}: Usage: winewrap EXEC [ARGS...]" 1>&2 
    exit 1 
fi 

EXEC=("${1}") 
shift 

for p in "${@}"; do 
    if [ -e "${p}" ]; then 
    p="$(winepath -w -- "${p}")" 
    fi 
    push EXEC "${p}" 
done 

exec "${EXEC[@]}" 
+0

定义“不可移植”。我不介意需要/ bin/bash而不是/ bin/sh,但是我不愿意要求最近的版本。有人把Unix shell脚本的可移植性矩阵放在一起(也就是说,哪些功能可用,哪些版本的哪些平台上的贝壳)? – 2008-09-22 17:13:45