Как мне правильно избежать такого пути к файлу в командной строке Windows? Тот, у которого в имени файла есть пробелы, проценты и переменные, такие как %cd% и %errorlevel%, без расширения переменных? Возможно ли это?
Например, запустите C:\Users\the impossible %cd% filepath.exe
Я искал и пробовал все вокруг для экранирования процентов и экранирования кавычек. Без переменных в имени файла это работает. Однако, если имя файла содержит проценты с такими переменными, как %cd% или %errorlevel%, ничего не работает вообще, независимо от какой-либо escape-последовательности.
Вещи, которые я пробовал:
"C:\Users\the impossible %cd% filepath.exe"
"C:\Users\the impossible %%cd%% filepath.exe"
"C:\Users\the impossible ^%cd^% filepath.exe"
В контексте командной строки существуют другие правила экранирования, чем в пакетном файле.
В контексте командной строки невозможно экранировать знак процента, но есть способ избежать его.
Итак, в вашем случае вы можете использовать:
^"C:\Users\the^ impossible^ %cd^%^ filepath.exe^"
Чтобы иметь возможность использовать курсор в имени файла, кавычки должны быть экранированы.
Но знак каретки не может избежать знака процента %cd^%
Парсер пытается найти переменную с именем cd^
, если такой переменной нет, он просто удаляет курсор и текст остается нетронутым.
Каретки перед пробелами необходимы для сохранения целостности имени файла.
Но если такая переменная существует, команда завершится неудачно:
set "cd^=FAIL"
Существует второй вариант, в котором можно избежать одиночных знаков процента.
for /F "tokens=1-31" %%= in ("1") do "C:\Users\the impossible %%=cd%%= filepath.exe"
Одиночный знак процента экранируется путем преобразования его в %%=
Это работает, поскольку первый знак процента просто остается на месте, а %=
расширяется до нуля.
На одной из фаз пакетного парсера синтаксический анализатор пытается расширить %=cd%
, но переменная не может начинаться со знака равенства, поэтому это безвредно.
Этот вариант является пуленепробиваемым, никакая предопределенная переменная не может его нарушить.
Эту технику можно адаптировать так, чтобы для выхода из %=
требовался только один %
.
for /F "tokens=1-31 delims= = " %%= in ("1=2=3=4=5=6=7=8=9=0=1=2=3=4=5=6=7=8=9=0=1=2=3=4=%=6=7") do (
echo "%=cd%=cd expands to '%cd%' special chars aren't a problem &<>|"
"C:\Users\the impossible %=cd%= filepath.exe"
)
В окне командной строки в этом случае необходимо использовать:
^"C:\Users\the^ impossible^ ^%cd^%^ filepath.exe^"`
Вывод справки по запуску cmd /?
в окне командной строки на последней странице справки объясняет, что имя файла (или любая другая строка аргумента) с пробелом или одним из этих символов &()[]{}^=;!'+,`~
(или буквально для интерпретации <>|
, как в строке пароля/парольной фразы) должен быть заключен в "
.
Все символы внутри строки аргумента, заключенной в "
, интерпретируются буквально, включая символ ^
, за исключением %
(всегда) и !
при включенном расширении отложенной переменной, которое отключено по умолчанию в Windows.
%
интерпретируется как начало/конец ссылки на переменную среды в командной строке, введенной в окне командной строки (или как ссылка на переменную цикла в случае цикла FOR). Но по сравнению с обработкой командной строки в пакетном файле что-то вроде %cd%
заменяется перед выполнением командной строки чем-то другим только в том случае, если действительно существует динамическая переменная или переменная среды с таким именем. Что-то вроде %UnknownVariable%
в строке имени файла не заменяется пустой строкой при выполнении командной строки, введенной в окне командной строки, при обработке командного файла %UnknownVariable%
удаляется из командной строки перед выполнением, если нет переменной с именем UnknownVariable
в настоящее время определено при обработке командной строки.
Причины разницы в обработке строк между двумя %
между выполнением командной строки и выполнением пакетного файла просты:
%
, что не так уж необычно, как думают многие, или командную строку с несколькими %
, например, для запуска исполняемого файла обработки изображений с такими параметрами, как width=75% height=50%
. Такие параметры можно записать в пакетном файле как width=75%% height=50%%
, т.е. е. знак процента для буквальной интерпретации экранируется знаком «больше процентов», чтобы не интерпретировать его как начало (или конец) переменной, цикла (внутри цикла FOR) или ссылку на строку аргумента пакетного файла.%Variable Name%
, введенный пользователем в окне командной строки, предназначен для ссылки на существующую переменную. Если динамическая переменная или переменная среды с именем Variable Name
отсутствует, пользователь либо допустил ошибку при вводе, либо %Variable Name%
вообще не ссылается на переменную. Командный процессор Windows при обработке пакетного файла может ожидать, что создатель пакетного файла не допустил опечатки. Это также очень распространено в пакетных файлах, ссылающихся на переменные, которые в настоящее время не существуют при обработке командной строки перед ее выполнением. Подумайте о переменных, определенных с необязательными параметрами, которые не существуют, если параметры не используются, или о ссылке на переменную, где при первом выполнении командной строки переменная, на которую ссылаются, еще не существует, но существует позже при повторном выполнении той же командной строки.Командный процессор Windows заменяет %Variable Name%
всегда значением указанной переменной или пустой строкой, если нет переменной с именем %Variable Name%
при обработке пакетного файла, но заменяет ссылку на переменную только в том случае, если переменная действительно существует при обработке командной строки, введенной в окно командной строки или передается cmd.exe
после опции /C
или опции /K
при ее запуске.
Вывод справки по запуску set /?
в окне командной строки также описывает наиболее часто используемые динамические переменные (не переменные среды). CD
— одна из динамических переменных. Строка %cd%
в имени файла, введенная в окне командной строки или прочитанная из пакетного файла, по этой причине всегда интерпретируется как ссылка на динамическую переменную CD
.
В пакетном файле можно использовать:
"C:\Users\the impossible %%cd%% filepath.exe"
Но специальное правило экранирования со знаком процента, оставленным вместо знака процента для буквальной интерпретации второго знака процента, предназначено только для пакетных файлов, а не для окна командной строки (из-за возможности ссылки на строку аргумента пакетного файла).
Следующая строка не может использоваться ни в окне командной строки, ни в пакетном файле, поскольку ^
внутри строки аргумента, заключенной в "
, интерпретируется буквально, а не как escape-символ.
"C:\Users\the impossible ^%cd^% filepath.exe"
Решение не заключать строку аргумента в "
специальным исключением из стандартных правил синтаксиса в этом случае использования, а вместо этого экранировать ^
каждым символом, например "
и %
, а также пробелом и использовать:
^"C:\Users\the^ impossible^ ^%cd^%^ filepath.exe^"`
^"
в начале указывает cmd.exe
интерпретировать "
буквально, а не как начало строки аргумента в двойных кавычках.
^
слева от каждого символа пробела указывает cmd.exe
интерпретировать пробел буквально, а не как разделитель строк аргументов.
^%
предписывает cmd.exe
интерпретировать знак процента в этом случае буквально, а не как начало/конец ссылки на существующую переменную (или в цикле FOR как ссылку на переменную цикла).
^"
в конце указывает cmd.exe
интерпретировать "
буквально, а не как конец строки аргумента в двойных кавычках.
В результате строка имени файла с символами курсора интерпретируется как экранирующие символы с помощью cmd.exe
как строки аргумента:
"C:\Users\the impossible %cd% filepath.exe"
Эта строка теперь передается в функцию библиотеки ядра Windows CreateProcess, при этом окружающие "
требуются, поскольку CreateProcess
анализирует эту строку командной строки, а также, чтобы выяснить, какой исполняемый файл запускать, а имя файла содержит пробелы и знаки процента для интерпретации также буквально CreateProcess
как это делается для первой строки аргумента, заключенной в двойные кавычки.