<p>The following shell script takes a list of arguments, turns Unix paths into WINE/Windows paths and invokes the given executable under WINE.</p>

<pre><code>#! /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
</code></pre>

<p>However, there's something wrong with the quotation of command-line arguments.</p>

<pre><code>$ 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'
</code></pre>

<p>Note that:</p>

<ol>
<li>The path to the executable is being chopped off at the first space, even though it is single-quoted.</li>
<li>The literal "\t" in the last path is being transformed into a tab character.</li>
</ol>

<p>Obviously, the quotations aren't being parsed the way I intended by the shell. How can I avoid these errors?</p>

<p>EDIT: The "\t" is being expanded through two levels of indirection: first, <code>"$p"</code> (and/or <code>"$ARGS"</code>) is being expanded into <code>Z:\tmp\smtlib3cee8b.smt</code>; then, <code>\t</code> is being expanded into the tab character. This is (seemingly) equivalent to</p>

<pre><code>Y='y\ty'
Z="z${Y}z"
echo $Z
</code></pre>

<p>which yields </p>

<pre><code>zy\tyz
</code></pre>

<p>and <em>not</em></p>

<pre><code>zy  yz
</code></pre>

<p>UPDATE: <code>eval "$CMD"</code> does the trick. The "<code>\t</code>" problem seems to be echo's fault: "If the first operand is -n, or if any of the operands contain a backslash ( '\' ) character, the results are implementation-defined." (<a href="http://www.opengroup.org/onlinepubs/009695399/utilities/echo.html" rel="nofollow noreferrer">POSIX specification of <code>echo</code></a>)</p>

[{'answer_id': 36113, 'author': 'Kyle Cronin', 'author_id': 658, 'author_profile': 'https://Stackoverflow.com/users/658', 'pm_score': 0, 'selected': False, 'text': '<p>You can try preceeding the spaces with \\ like so:</p>\n\n<pre><code>/home/chris/.wine/drive_c/Program Files/Microsoft\\ Research/Z3-1.3.6/bin/z3.exe\n</code></pre>\n\n<p>You can also do the same with your \\t problem - replace it with \\\\t.</p>\n'}, {'answer_id': 36190, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 0, 'selected': False, 'text': "<p>replace the last line from $CMD to just</p>\n\n<p>wine '$EXEC' $ARGS</p>\n\n<p>You'll note that the error is ''/home/chris/.wine/drive_c/Program' and not '/home/chris/.wine/drive_c/Program'</p>\n\n<p>The single quotes are not being interpolated properly, and the string is being split by spaces.</p>\n"}, {'answer_id': 42005, 'author': 'WMR', 'author_id': 2844, 'author_profile': 'https://Stackoverflow.com/users/2844', 'pm_score': 2, 'selected': True, 'text': '<p>I you do want to have the assignment to CMD you should use </p>\n\n<p><code>eval $CMD</code> </p>\n\n<p>instead of just <code>$CMD</code> in the last line of your script. This should solve your problem with spaces in the paths, I don\'t know what to do about the "\\t" problem.</p>\n'}, {'answer_id': 112558, 'author': 'andrewdotn', 'author_id': 14558, 'author_profile': 'https://Stackoverflow.com/users/14558', 'pm_score': 2, 'selected': False, 'text': '<ul>\n<li>bash’s arrays are unportable but the only sane way to handle argument lists in shell</li>\n<li>The number of arguments is in ${#}</li>\n<li>Bad stuff will happen with your script if there are filenames starting with a dash in the current directory</li>\n<li>If the last line of your script just runs a program, and there are no traps on exit, you should exec it</li>\n</ul>\n\n<p>With that in mind</p>\n\n<pre><code>#! /bin/bash\n\n# push ARRAY arg1 arg2 ...\n# adds arg1, arg2, ... to the end of ARRAY\nfunction push() {\n    local ARRAY_NAME="${1}"\n    shift\n    for ARG in "${@}"; do\n        eval "${ARRAY_NAME}[\\${#${ARRAY_NAME}[@]}]=\\${ARG}"\n    done\n}\n\nPROG="$(basename -- "${0}")"\n\nif (( ${#} &lt; 1 )); then\n  # Error messages should state the program name and go to stderr\n  echo "${PROG}: Usage: winewrap EXEC [ARGS...]" 1&gt;&amp;2\n  exit 1\nfi\n\nEXEC=("${1}")\nshift\n\nfor p in "${@}"; do\n  if [ -e "${p}" ]; then\n    p="$(winepath -w -- "${p}")"\n  fi\n  push EXEC "${p}"\ndone\n\nexec "${EXEC[@]}"\n</code></pre>\n'}]
['https://Stackoverflow.com/questions/36109', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/1412/']