Windows PATH变量中的空格和括号会破坏批处理文件


14

因此,我的路径变量(系统->广告设置->环境变量->系统->路径)设置为:

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.

那么,这是胡扯吗?

特别:

  • 路径中的目录可以用引号正确转义,但不能有空格=很好
  • 路径中的目录可以正确地用引号引起来,并且具有空格,但是没有括号=可以
  • 路径中的目录已使用引号正确转义,并且具有空格并且带有括号= ERROR

这里发生了什么?我怎样才能解决这个问题?我可能会求助于交汇点,以使我的工具仍然可以解决,但是,如果您对此有所了解,请告诉我:)


根据我对当前问题的理解,以上答案是正确的,并且它取决于考虑到SET是命令,而PATH是其参数的一部分,其余部分是新的PATH字符串。因此,IMO,不是因为它没有稀疏记录,而是更像是一个晦涩的边缘案例。我在这个问题上花了几个小时。
David A. Gray,

Answers:


13

如果“块”内的一行中有未转义的括号,则可能发生这种情况(该块也使用括号来定界)。

通常,您可以通过启用延迟扩展并使用!var!代替来解决此问题%var%。如果不看代码,我没有其他更多建议。



13

(a)MS-Windows PATH环境变量(PATH命令)中不应包含任何引号,或者(b)在(SET命令)之后的整个表达式中应包含引号。不幸的是,尽管MS确实指出如果使用了引号,但它们确实会包含在变量的值中(Windows XP命令行参考),MS并没有很好地对此进行说明。

$ 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-Windows时编写MS-DOS的,而您的命令是针对MS-Windows的。OP确实询问了有关MS-Windows的问题。那么,为什么不称呼它MS-DOS。甚至您的链接都说NT(即-Windows。以前是9X和NT,现在只是NT)。Windows和MS-DOS是两种不同的操作系统。我以前曾经看到过Windows命令提示符错误地调用了DOS,但即使这样也不如您所说的那样错误。
barlop 2014年

@barlop,您当然是正确的。感谢您的修改。在Windows-95之前,Windows是基于DOS构建的应用程序。您可以通过win在DOS中键入命令来启动Windows 。实际上,在Windows-3.1之前,诸如Zork和WordStar的所有东西都是DOS应用程序。然后从Windows-98开始,没有DOS。但是我认为像我这样的旧计时器仍然错误地将CMD shell称为DOS shell。很抱歉造成您的困惑,再次感谢您澄清我回答的意图。
Mark Mikofski 2014年

@MarkMikofski实际上Windows 9X(95/98 / ME)也可以说是基于DOS构建的。例如,您可以编辑一些文件(也许是msdos.sys)和一些诸如bootGUI = 0的选项,并停止Windows加载tokyopc.org/newsletter/1996/08/msdosed.html 是否可以从那里加载Windows我不知道不知道。Win9X启动盘被认为是DOS。知道您在说什么的老计时器通常是最后一个犯错误的人,他们错误地调用了Windows命令提示符DOS。并且是第一个最坚决不是DOS的人。
barlop

1
尝试建议(SET PATH=%PATH%;C:\Program Files (x86)\path with special characters)吗?完全错了!
JosefZ 2015年

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 2015年

1

我经历过类似的事情。Microsoft在这里解释了此问题:http : //support.microsoft.com/kb/329308

基本上,代替尝试通过System-> Adv Settings-> Env Vars-> System-> PATH更改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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.