2008-08-30 148 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

相關問題