Quoting command line arguments in shell scripts

The following shell script takes a list of arguments, turns Unix paths into WINE / Windows paths, and calls the given executable in 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

However, something is wrong with the quote of command line arguments.

$ 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'

Note that:

  • The path to the executable file is chopped off in the first space, even if it is single.
  • The literal "\ t" in the last path is converted to a tab character.

Obviously, quotes are not parsed as I expected by the shell. How to avoid these errors?

EDIT: "\ t" expands through two levels of indirection: first, "$p"(and / or "$ARGS") expands to Z:\tmp\smtlib3cee8b.smt; It \texpands to a tab character. This is (similar) equivalent

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

what gives

zy\tyz

but not

zy  yz

UPDATE: eval "$CMD" . "\t", -, : " -n, - (" \ "), ". ( POSIX echo)

+3
4

CMD,

eval $CMD

$CMD script. , , "\ t".

+1
  • bash s ,
  • ${#}
  • script, ,
  • script , ,

#! /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[@]}"
+3

You can try spaces in spaces as follows:

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

You can also do the same with your \ t problem - replace it with \\ t.

0
source

replace the last line from $ CMD with just

wine '$ EXEC' $ ARGS

You will notice that the error is '/home/chris/.wine/drive_c/Program' and not '/home/chris/.wine/drive_c/Program'

Single quotes are not interpolated properly, and the string is separated by spaces.

0
source

Source: https://habr.com/ru/post/1696605/


All Articles