Frage

Das folgende Shell-Skript nimmt eine Liste von Argumenten, wandelt Unix-Pfade in WINE/Windows-Pfade um und ruft die angegebene ausführbare Datei unter WINE auf.

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

Allerdings stimmt etwas mit der Anführung von Befehlszeilenargumenten nicht.

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

Beachten Sie, dass:

  1. Der Pfad zur ausführbaren Datei wird am ersten Leerzeichen abgeschnitten, obwohl er in einfache Anführungszeichen gesetzt ist.
  2. Das Literal „ “ im letzten Pfad wird in ein Tabulatorzeichen umgewandelt.

Offensichtlich werden die Zitate von der Shell nicht so analysiert, wie ich es beabsichtigt hatte.Wie kann ich diese Fehler vermeiden?

BEARBEITEN:Das „ “ wird durch zwei Indirektionsebenen erweitert:Erste, "$p" (und/oder "$ARGS") wird erweitert in Z:\tmp\smtlib3cee8b.smt;Dann, \t wird zum Tabulatorzeichen erweitert.Dies ist (scheinbar) gleichbedeutend mit

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

was ergibt

zy\tyz

Und nicht

zy  yz

AKTUALISIEREN: eval "$CMD" macht den Trick.Der "\t„Das Problem scheint Echos Schuld zu sein:"Wenn der erste Operand -n ist oder wenn einer der Operanden einen Backslash -Zeichen ('') enthält, sind die Ergebnisse implementiert." (POSIX-Spezifikation von echo)

War es hilfreich?

Lösung

Wenn Sie die Zuordnung zu CMD haben möchten, sollten Sie diese verwenden

eval $CMD

statt nur $CMD in der letzten Zeile Ihres Skripts.Dies sollte Ihr Problem mit Leerzeichen in den Pfaden lösen. Ich weiß nicht, was ich gegen das „ “-Problem tun soll.

Andere Tipps

  • Die Arrays von Bash sind nicht portierbar, aber die einzig vernünftige Möglichkeit, Argumentlisten in der Shell zu verarbeiten
  • Die Anzahl der Argumente ist in ${#}
  • Wenn im aktuellen Verzeichnis Dateinamen mit einem Bindestrich beginnen, kann es zu schlimmen Problemen mit Ihrem Skript kommen
  • Wenn die letzte Zeile Ihres Skripts nur ein Programm ausführt und es beim Beenden keine Traps gibt, sollten Sie es ausführen

In diesem Sinne

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

Ersetzen Sie die letzte Zeile von $CMD durch just

wine '$EXEC' $ARGS

Sie werden feststellen, dass der Fehler „/home/chris/.wine/drive_c/Program“ und nicht „/home/chris/.wine/drive_c/Program“ lautet.

Die einfachen Anführungszeichen werden nicht richtig interpoliert und die Zeichenfolge wird durch Leerzeichen aufgeteilt.

Sie können versuchen, den Leerzeichen ein \ voranzustellen, etwa so:

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

Sie können das Gleiche auch mit Ihrem -Problem tun – ersetzen Sie es durch \ .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top