Cygwin: вызывает пакетный файл с аргументом, перенаправлением вывода и сложными путями Windows - PullRequest
1 голос
/ 29 апреля 2019

Как вызвать командный файл из скрипта bash под Cygwin, с ...

  • абсолютный путь к пакетному файлу
  • аргумент (ы) пакетного файла, представляющий абсолютный (оконный) путь (и)
  • перенаправление вывода в файл по абсолютному пути

где ...

  • все пути могут содержать пробелы и специальные символы, такие как скобки
  • все пути изначально присутствуют только в формате Unix в скрипте bash?

У меня есть пакетный скрипт Windows C: \ Program Files (x86) \ bin \ script.bat, который принимает (windows) путь к входному файлу в качестве аргумента - пример:

@ECHO OFF
echo "This is script.bat. The value of the first argument is [%~1]"

Я хочу перенаправить вывод файла script.bat в выходной файл по другому абсолютному пути.

В командной строке Windows (cmd.exe) я бы вызвал команду следующим образом:

C:\> "C:\Program Files (x86)\bin\script.bat" "C:\Input Path\input.txt" > "C:\Output Path\output.txt"
output.txt: This is script.bat. The value of the first argument is [C:\Input Path\input.txt].

Я могу опустить двойные кавычки вокруг сценария и цели перенаправления, если я применяю «экранирование в пакетном стиле», но это не работает для аргумента (по некоторым причинам):

C:\> C:\Program^ Files^ ^(x86^)\bin\script.bat "C:\Input Path\input.txt" > C:\Output^ Path\output.txt
output.txt: This is script.bat. The value of the first argument is [C:\Input Path\input.txt].

... но:

C:\> C:\Program^ Files^ ^(x86^)\bin\script.bat C:\Input^ Path\input.txt > C:\Output^ Path\output.txt
output.txt: This is script.bat. The value of the first argument is [C:\Input].

Я также могу заключить команду в дополнительный вызов cmd.exe, используя дополнительные двойные кавычки вокруг всего термина:

C:\> cmd.exe /C ""C:\Program Files (x86)\bin\script.bat" "C:\Input Path\input.txt" > "C:\Output Path\output.txt""
output.txt: This is script.bat. The value of the first argument is [C:\Input Path\input.txt].

C:\> cmd.exe /C "C:\Program^ Files^ ^(x86^)\bin\script.bat "C:\Input Path\input.txt" > C:\Output^ Path\output.txt"
output.txt: This is script.bat. The value of the first argument is [C:\Input Path\input.txt].

Я также могу применить перенаправление вывода к внешнему экземпляру cmd.exe:

C:\> cmd.exe /C ""C:\Program Files (x86)\bin\script.bat" "C:\Input Path\input.txt"" > "C:\Output Path\output.txt"
output.txt: This is script.bat. The value of the first argument is [C:\Input Path\input.txt].

C:\> cmd.exe /C "C:\Program^ Files^ ^(x86^)\bin\script.bat "C:\Input Path\input.txt"" > C:\Output^ Path\output.txt
output.txt: This is script.bat. The value of the first argument is [C:\Input Path\input.txt].

Пока все хорошо. Но как я могу вызвать любую из вышеперечисленных командных строк из скрипта bash под Cygwin?

Все пути изначально существуют только в формате Unix:

#!/bin/sh
BIN_UNIX="/cygdrive/c/Program Files (x86)/bin/script.bat"
ARG_UNIX="/cygdrive/c/Input Path/input.txt"
OUT_UNIX="/cygdrive/c/Output Path/output.txt"

Обратите внимание, что файл $ OUT_UNIX не существует на момент вызова скрипта (поэтому 'cygpath --dos ...' не работает).

Я экспериментировал с десятками более или менее неуклюжих комбинаций путей Unix / Windows (преобразование с помощью cygpath), без кавычек, одинарных кавычек, двойных кавычек, без экранирования, экранирование в "bash-style", экранирование в "пакетном стиле" и т. д. Единственное работающее решение, которое я смог найти, зависит от пути пакетного сценария в стиле 8.3, который устраняет пробелы и специальные символы:

#!/bin/sh
# [...]
BIN_DOS=$( cygpath --dos "${BIN_UNIX}" )
ARG_WIN=$( cygpath --windows "${ARG_UNIX}" )
cmd /C "${BIN_DOS}" "${ARG_WIN}" > "$OUT_UNIX"

Но должен быть более систематический и надежный способ сделать это, верно?


Смежные вопросы, которые не полностью отвечают на мой вопрос:

Почему Cygwin может запускать сценарии .bat?

Пакеты Windows в Cygwin с пробелами в пути и аргументами

правильное цитирование cmd.exe для нескольких аргументов

Как передать параметры командной строки с пробелом в командном файле

1 Ответ

3 голосов
/ 29 апреля 2019

Вы можете использовать

BIN_WIN=$( cygpath --windows "${BIN_UNIX}" )
ARG_WIN=$( cygpath --windows "${ARG_UNIX}" )
OUT_WIN=$( cygpath --windows "${OUT_UNIX}" )
cmd /c CALL "$BIN_WIN" "${ARG_WIN}" > "$OUT_WIN"

Важным моментом является CALL перед вашей командой.

cmd /c не удается запустить команду с пробелами внутри, поскольку она разбивает команду, даже если есть кавычки.

cmd /c также будет работать без CALL, но с дополнительными кавычками.

cmd /c "  "C:\Program Files (x86)\bin\script.bat" "args"   "

Но кажется, что невозможно передать необработанные кавычки из cygwin в cmd.exe, потому что cygwin переводит кавычки в \", поэтому выражение становится

cmd /c \"  "C:\Program Files (x86)\bin\script.bat" "args"   \"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...