Пробелы и скобки в переменной Windows PATH портят пакетные файлы


14

Итак, моя переменная пути (System-> Adv Settings-> Env Vars-> System-> PATH) установлена ​​в:

C:\Python26\Lib\site-packages\PyQt4\bin;
%SystemRoot%\system32;
%SystemRoot%;
%SystemRoot%\System32\Wbem;
%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;
C:\Python26\;
C:\Python26\Scripts\;
C:\cygwin\bin;
"C:\PathWithSpaces\What_is_this_bullshit";
"C:\PathWithSpaces 1.5\What_is_this_bullshit_1.5";
"C:\PathWithSpaces (2.0)\What_is_this_bullshit_2.0";
"C:\Program Files (x86)\IronPython 2.6";
"C:\Program Files (x86)\Subversion\bin";
"C:\Program Files (x86)\Git\cmd";
"C:\Program Files (x86)\PuTTY";
"C:\Program Files (x86)\Mercurial";
Z:\droid\android-sdk-windows\tools;

Хотя, очевидно, без перевода строки.

Обратите внимание на строки, содержащие: PathWithSpacesу первого нет пробелов, у второго - пробел, а у третьего - пробел, за которым следует скобка.

Теперь обратите внимание на вывод этого пакетного файла:

C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\>vcvars32.bat
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin>"C:\Program Files (x86
)\Microsoft Visual Studio 9.0\Common7\Tools\vsvars32.bat"
Setting environment for using Microsoft Visual Studio 2008 x86 tools.
\What_is_this_bullshit_2.0";"C:\Program was unexpected at this time.
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin>      set "PATH=C:\Pro
gram Files\Microsoft SDKs\Windows\v6.0A\bin;C:\Python26\Lib\site-packages\PyQt4\
bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\
WindowsPowerShell\v1.0\;C:\Python26\;C:\Python26\Scripts\;C:\cygwin\bin;"C:\Path
WithSpaces\What_is_this_bullshit";"C:\PathWithSpaces 1.5\What_is_this_bullshit_1
.5";"C:\PathWithSpaces (2.0)\What_is_this_bullshit_2.0";"C:\Program Files (x86)\
IronPython 2.6";"C:\Program Files (x86)\Subversion\bin";"C:\Program Files (x86)\
Git\cmd";"C:\Program Files (x86)\PuTTY";"C:\Program Files (x86)\Mercurial";Z:\dr
oid\android-sdk-windows\tools;"

или конкретно строка:

\What_is_this_bullshit_2.0";"C:\Program was unexpected at this time.

Итак, что это за фигня?

В частности:

  • Каталог в пути, который правильно экранирован кавычками, но без пробелов = штраф
  • Каталог в пути, который корректно экранируется кавычками и имеет пробелы, но без скобок = штраф
  • Каталог в пути, правильно экранированный кавычками, с пробелами и круглыми скобками = ОШИБКА

Что тут происходит? Как я могу это исправить? Я, вероятно, прибегну к точке соединения, чтобы мои инструменты все еще работали как обходной путь, но если у вас есть какое-либо понимание этого, пожалуйста, дайте мне знать :)


Основываясь на моем понимании рассматриваемых проблем, приведенный выше ответ является правильным, и он основан на учете, что SET - это команда, а PATH - часть ее аргумента, баланс которой - новая строка PATH. Итак, IMO, дело не в том, что это редко документировано, а в том, что это скорее неясный крайний случай. Я просто потратил пару часов на эту проблему.
Дэвид А. Грей

Ответы:


13

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

Обычно это можно исправить, включив отложенное расширение и используя переменные !var!вместо %var%. Я не могу дать гораздо больше советов, не видя код.


19

Примечание для пользователей Windows на 64-битных системах

Progra ~ 1 = «Программные файлы» Progra ~ 2 = «Программные файлы (x86)»

https://confluence.atlassian.com/display/DOC/Setting+the+JAVA_HOME+Variable+in+Windows


1
Очень полезно для избавления от пробелов в переменной среды $ PATH при использовании MSYS в Windows. autoconf не играл хорошо, пока я не сделал это изменение.
Майк

13

Там должен либо (а) не будет никаких кавычек в PATH переменной MS-Windows , окружающей среды (команда PATH) или (б) должны быть кавычки вокруг всего выражения следуя (команда SET) . К сожалению, это не очень хорошо задокументировано MS, хотя они утверждают, что если используются кавычки, они будут включены в значение переменной (Справочник по командной строке Windows XP) .

$ SET BLAH="blah blah(1)"
$ ECHO %BLAH%
"blah blah(1)"
$ SET BLAH=blah blah(1)
$ ECHO %BLAH%
blah blah(1)

Это может вызвать проблемы, которые являются непоследовательными и поэтому трудно диагностируемыми. Например, если ваш путь включает в себя «C: \ Python27», ваш компьютер скажет «Python» не распознан как внутренняя или внешняя команда, работающая программа или пакетный файл ». когда вы пытаетесь выполнить Python. Однако некоторые библиотеки все еще могут быть доступны.

Вам не нужно «экранировать» пробелы или скобки. Если вам нужно экранировать специальные символы, заключите в кавычки все выражение, включая имя переменной.

SET "PATH=%PATH%;C:\Program Files (x86)\path with special characters"

или вы можете использовать скобки тоже.

(SET VAR=can't contain ampersand, parentheses, pipe, gt or lt)

Обратите внимание, что двойные кавычки должны быть в парах.

(SET VAR=illegal characters!@#$%^*_-+={}[]\:;""',./?)
echo %VAR%
illegal characters!@#$%*_-+={}[]\:;""',./?

Однако, вероятно, нет никаких символов, которые являются допустимыми путями, которые могли бы вызвать проблему с командой SET.



1
Вы действительно написали MS-DOS, когда имели в виду MS-Windows, а ваши команды были для MS-Windows. ОП спрашивал про MS-Windows. Так почему вы называете это MS-DOS, я не знаю. Даже ваши ссылки говорили NT (то есть - Windows. Раньше это были 9X и NT, теперь это просто NT). Windows и MS-DOS - две разные операционные системы. Я видел командную строку windows, по ошибке названную DOS, но даже это не так неправильно, как вы ее назвали.
Бароп

@ barlop, конечно, ты прав. Спасибо за правки. До Windows-95 Windows была приложением, созданным поверх DOS. Вы можете запустить Windows, набрав winкоманду в DOS. Фактически до Windows-3.1 все, как Zork и WordStar, были приложениями для DOS. Затем, начиная с Windows-98, не было DOS. Но я думаю, что некоторые старые таймеры, такие как я, по-прежнему называют оболочку CMD ошибочно оболочкой DOS. Извините за путаницу, и еще раз спасибо за разъяснение цели моего ответа.
Марк Микофски

@MarkMikofski На самом деле Windows 9X (95/98 / ME), вероятно, также была построена на DOS. Вы можете, например , редактировать некоторый файл (возможно msdos.sys) некоторые опции (ы) , как BootGUI = 0 и стоп окно загрузки tokyopc.org/newsletter/1996/08/msdosed.html ли вы могли бы загрузить окна оттуда я не» я знаю А загрузочный диск Win9X считается DOS. Старые таймеры, которые знают, о чем они говорят, как вы, обычно являются последними, кто совершил ошибку, вызвав командную строку Windows DOS. И первые люди, которые будут самыми непреклонными, что это не DOS.
Бароп

1
Вы пытались посоветовали (SET PATH=%PATH%;C:\Program Files (x86)\path with special characters)? Это совершенно неправильно!
JosefZ

2

Microsoft документирует проблему в « Ошибка запуска сценариев командной оболочки, которые включают скобки ».

Решение, которое они предлагают, заключается в использовании отложенного расширения.

SETLOCAL ENABLEDELAYEDEXPANSION
SET VAR=string containing ( and ) ...
IF "y" == "y" (
    ECHO !VAR! %VAR%
)
ENDLOCAL

Для установки пути в блоке if вместо использования SET PATH=вы, вероятно, должны использовать PATHкоманду.

SET AddToPath=C:\Program Files (x86)\Whatever

SETLOCAL ENABLEDELAYEDEXPANSION
IF "%X%" == "%Y%" (
    ECHO Adding !AddToPath! to path !PATH!
    PATH !AddToPath!;!PATH!
)

Для других переменных другим решением может быть использование кавычек, но вокруг всего этого:

SET "MyVar=C:\Program Files (x86)\Whatever"

1

Джои в своем ответе говорит

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

и это правда. Если есть неэкранированные скобки, следует избегать их. Это то, что я сделал; Я заменил

set PATH=some_path;%PATH%

с

set PATH="some_path;%PATH%"

и это решило проблему.


2
Нет. Вы должны использоватьset "PATH=some_path;%PATH%"
JosefZ

1

Я испытал нечто подобное. Microsoft объясняет проблему здесь: http://support.microsoft.com/kb/329308

По сути, вместо изменения переменной Path через System-> Adv Settings-> Env Vars-> System-> PATH, попробуйте

My Computer->Manage->Computer Management (local)-> Properties-> Advanced-> Environment variables-> Settings

1

В Windows 8 я нашел очень мало успеха с любым из этих методов. Круглые скобки не работают, кавычки работают, но «путь», который вы изменяете таким образом, не является путем, который используется для поиска исполняемых файлов, а, cmdпохоже, все еще использует системный путь, который он унаследовал при открытии окна.

пример: после определения архитектуры процессора я хочу добавить пару путей к переменной среды PATH. На самом деле, даже простое добавление их временно будет работать, так как они нужны мне только во время работы командного файла. Но это даже не работает.

echo %path%отображает системный PATH во время cmdзапуска.

set path="%path%;%programfiles(x86)%\company\program\subdir"работает, но теперь %path%содержит все, что заключено в кавычки, и если я пытаюсь запустить программу в subdir откуда-то еще, это не удается. Использование круглых скобок вместо кавычек не работает .

Еще одна вещь, которую я заметил, заключается в том, что та же команда будет работать, если она введена в интерактивном режиме cmd, но не при обнаружении в командном файле. Это страшно. Еще одна странность - прерывистая потеря последнего символа значения переменной окружения! Другое несоответствие касается сторонних программ: некоторые могут обрабатывать a %var%как параметр, другие - нет.


1

У меня были огромные проблемы с выполнением следующей работы в Win8, пока я не добавил двойные кавычки вокруг значения, которое я устанавливал для переменной fromFile. С учетом этого, когда fromFile содержал имя файла с круглыми скобками, следующая строка, которая пыталась выполнить подстановку строки для генерации переменной toFile, не работала. Обратите внимание, что я использую отложенное расширение для оценки переменной во время выполнения, а не во время синтаксического анализа (соответствующего экземпляра CALL)

::-- BATCH file that creates an *_576_5.* file from an *_640_t.* one (copying it)
::-- Author: George Birbilis (http://zoomicon.com)
::-- Credits: String replacement based on http://www.dostips.com/DtTipsStringManipulation.php

@ECHO OFF

::-- Loop for all files recursively --::

FOR /R %%f in (*_640_t.*) DO CALL :process %%f

ECHO(
PAUSE

GOTO :EOF

::-- Per-file actions --::

:process

:: Display progress...
::ECHO Processing %*
<nul (set/p dummy=.)

SETLOCAL ENABLEDELAYEDEXPANSION
SET fromFile="%*"
SET toFile=!fromFile:_640_t=_576_t!

IF NOT EXIST %toFile% CALL :generate %fromFile% %toFile%

GOTO :EOF

::-- Generate missing file --::

:generate

ECHO(
ECHO COPY %*
COPY %*

::PAUSE

GOTO :EOF
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.