У меня есть пакетный файл, который получает свое собственное короткое имя пути (чтобы исключить пробелы, которые не нравятся gcc) для использования в последующих командах:
set base=%~d0%~sp0
Это прекрасно работает в большинстве случаев; например, если пакетный файл расположен в C:\Program Files, значением %base% будет C:\PROGRA~1, и gcc будет доволен.
Однако это не работает, если пакетный файл находится в каталоге с «&» в имени. Если он находится в каталоге с именем «C:\Here & There», приведенная выше команда расширяется до
set base=C:\HERE&T~1\
который обрабатывается как две команды, выдающие сообщение об ошибке 'T~1\' is not recognized as an internal or external command, operable program or batch file.
Если я поставлю его в кавычки:
set base = "%~d0%~sp0"
Тогда команда работает, и значение %base% равно "C:\HERE&T~1\"
(включая кавычки). Но затем кавычки ломают что-то еще дальше в файле, когда я использую его для построения пути к классам Java:
java -cp .;"C:\HERE&T~1\"Jars\* foo
в котором говорится: «Система не может найти указанный файл» (относится к "C:\HERE&T~1\"Jars\*
в пути к классам).
Может ли кто-нибудь предложить способ обойти этот беспорядок Microsoft?
[Редактировать]
По запросу Mofi ниже, вот минимальный воспроизводимый пример пакетного файла:
@echo off
set base=%~d0%~sp0
echo %base%
Если это выполняется в каталоге с именем «C:\Here & There», я бы хотел, чтобы вывод был
C:\HERE&T~1
без кавычек или другого постороннего вывода.
Вот фактический вывод при использовании CMD.EXE в качестве оболочки:
'T~1\' is not recognized as an internal or external command,
operable program or batch file.
C:\HERE
Если я изменю строку @echo off
на @echo on
, чтобы показать команды по мере их выполнения, я получу это (где «C:\Here & There>» — это приглашение, за которым следует фактическая команда, отображаемая перед выполнением):
C:\Here & There> set base=C:\HERE & T~1\
'T~1\' is not recognized as an internal or external command,
operable program or batch file.
C:\Here & There> echo C:\HERE
C:\HERE
Поскольку кавычки не должны быть частью значения, правильной командой SET будет
set "base=%~d0%~sp0"
Есть две проблемы, первая — расширение в команде SET
.
Этого можно избежать, заключив выражение в кавычки.
set "base=%~dps0"
Вторая проблема — это echo
, ее тоже можно избежать с помощью кавычек.
echo "%base%"
Но тогда и кавычки тоже видны.
В пакетном файле это можно решить с помощью отложенного расширения:
set "base=%~dps0"
setlocal EnableDelayedExpansion
echo !base!
Но в командной строке режим отложенного расширения не может быть изменен с помощью setlocal
, его можно установить только с помощью параметра /v:on
при запуске cmd.exe
cmd /v:on
set "base=%~dps0"
echo !base!