Следующий сценарий оболочки принимает список аргументов, превращает пути Unix в пути WINE / Windows и вызывает указанный исполняемый файл под WINE.
#! /bin/sh
if [ "${1+set}" != "set" ]
then
echo "Usage; winewrap EXEC [ARGS...]"
exit 1
fi
EXEC = ""
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" расширяется за счет двух уровней косвенности: во-первых, "$p" (и / или "$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)





Вы можете попробовать поставить перед пробелами \, например так:
/home/chris/.wine/drive_c/Program Files/Microsoft\ Research/Z3-1.3.6/bin/z3.exe
Вы также можете сделать то же самое с вашей проблемой \ t - замените ее на \\ t.
замените последнюю строку из $ CMD на просто
вино '$ EXEC' $ ARGS
Вы заметите, что это ошибка «/home/chris/.wine/drive_c/Program», а не «/home/chris/.wine/drive_c/Program».
Одиночные кавычки не интерполируются должным образом, а строка разделяется пробелами.
Если вы хотите, чтобы у вас было назначение на CMD, которое вы должны использовать
eval $CMD
вместо просто $CMD в последней строке вашего скрипта. Это должно решить вашу проблему с пробелами в путях, я не знаю, что делать с проблемой "\ t".
С этим в мыслях
#! /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[@]}"
Дайте определение «непереносимый». Я не против использования / bin / bash вместо / bin / sh, но я не решаюсь требовать последнюю версию. Кто-нибудь составил матрицу переносимости сценария оболочки Unix (т. Е. Какие функции доступны в каких версиях снаряды на каких платформах)?
Оба пути являются совершенно допустимыми путями Unix как вход в сценарий. Одиночные кавычки должны устранить необходимость в экранировании пробелов. И «\ t» автоматически генерируется командой
winepath(она превращает «/ tmp» в «Z: \ tmp»).