Пакетный файл Windows: путь с «&» интерпретируется как две команды

У меня есть пакетный файл, который получает свое собственное короткое имя пути (чтобы исключить пробелы, которые не нравятся 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
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
51
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Поскольку кавычки не должны быть частью значения, правильной командой 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!

Другие вопросы по теме