Windows批处理:“if exist”——路径存在但显示不存在——为什么?

3

我有一个批处理文件中的脚本 --

if not exist "%JAVA_HOME%" (
    echo JAVA_HOME '%JAVA_HOME%' path doesn't exist) --- (1)
else (
    echo Setting JAVA property to '%JAVA_HOME%\bin\java' --- (2)
        set "JAVA=%JAVA_HOME%\bin\java")

%JAVA_HOME%被设置为C:\Program Files (x86)\Java\jdk1.7.0_45。这个位置存在于我的计算机上,但以上代码执行时会执行第一行,为什么呢?

后续:

这让我非常困惑,我现在有这个脚本 --

if "x%JAVA_HOME%" == "x" (
  set  JAVA=java
  echo JAVA_HOME is not set. Unexpected results may occur.
  echo Set JAVA_HOME to the directory of your local JDK to avoid this message.
) else (
  if not exist "%JAVA_HOME%" (
    echo Here ----------------------------------> note this line !!
    echo JAVA_HOME '%JAVA_HOME%' path doesn't exist
    goto END
  ) else (
    echo Setting JAVA property to '%JAVA_HOME%\bin\java'
    set "JAVA=%JAVA_HOME%\bin\java"
  )
)
:END

%JAVA_HOME% 已经正确设置(它是 C:\Program Files (x86)\Java\jdk1.7.0_45)。但当我运行时,我会遇到错误 —

prompt> test.bat
prompt> \Java\jdk1.7.0_45' was unexpected at this time
prompt>      echo JAVA_HOME 'C:\Program Files (x86)\Java\jdk1.7.0_45' path does not exist

发生了什么?请注意,echo Here 这一行也没有执行。


你在关键字中使用了not。因此,如果它存在的话,它将显示为no。 - Monacraft
在echo语句中,将路径用双引号而不是单引号括起来,因为括号会导致问题。 - foxidrive
3个回答

3

Raymond Chen曾经说过

批处理语言并非设计而来,而是演化而成。

这就使得它充满了怪癖。其中之一就是它对括号非常挑剔。

以下代码在我的电脑上可以正常运行:

@echo off

if not exist "%JAVA_HOME%" (
    echo JAVA_HOME '%JAVA_HOME%' path doesn't exist
) else (
    echo Setting JAVA property to '%JAVA_HOME%\bin\java'
    set JAVA=%JAVA_HOME%\bin\java
)

我使用了 ) else (,一个单独的括号在自己一行上,并从echo语句中删除了括号。

您还需要检查双引号。像您所做的那样将变量名称放在引号内将从值中移除引号。这是一个例子:

C:\>set "test=foo bar"

C:\>echo %test%
foo bar

C:\>echo "%test%"
"foo bar"

如果您需要在变量值中引用引号,则将它们放在右侧,就像这样:

C:\>set test="foo bar"

C:\>echo %test%
"foo bar"

从零开始,选择前者会给你更多的灵活性(参见@foxidrive评论),但一切都取决于你要处理什么。

只是评论一下,在set命令中使用双引号是可以的,并且在许多情况下是必需的。 - foxidrive
1
我同意。我是在谈论整个集合表达式。我添加了示例代码以阐明我的观点。 - ixe013
1
是的,我明白了。在引号中加上变量名也非常有用,这样可以保护长路径名元素,但您仍然可以操纵变量而不会受到引号的干扰。 - foxidrive
嗨 @ixe013,我在之前的问题中添加了一些后续内容,非常感谢您的帮助。 - ramgorur
你的回显被发送到名为 note 的文件中,因为你使用了 > - ixe013
StackOverflow不是聊天室或论坛。如果我回答了你的问题,请接受它。如果你有其他问题,请发布一个新的问题。这样你将拥有整个社区的帮助,而不仅仅是我。它也会更有可能帮助到遇到类似问题的程序员。 - ixe013

3
您的JAVA_HOME路径中的括号会干扰if语句。我知道这很痛苦,但我建议使用8dot3名称。
call :SET8DOT3 JAVA_HOME %JAVA_HOME%


:SET8DOT3
set %1=%~fs2
goto :END

所以整个过程变成了...
call :SET8DOT3 JAVA_HOME "%JAVA_HOME%"

if "x%JAVA_HOME%" == "x" (
  set  JAVA=java
  echo JAVA_HOME is not set. Unexpected results may occur.
  echo Set JAVA_HOME to the directory of your local JDK to avoid this message.
) else (
  if not exist "%JAVA_HOME%" (
    echo Here ---------------------------------- note this line !!
    echo JAVA_HOME "%JAVA_HOME%" path doesn't exist
    goto END
  ) else (
    echo Setting JAVA property to "%JAVA_HOME%\bin\java"
    set "JAVA=%JAVA_HOME%\bin\java"
  )
)
goto :END

:SET8DOT3
set %1=%~fs2

:END

如果有人知道在条件部分中让if语句包含括号的方法,请告诉我。 - Okkenator
1
也许你应该在 Stack Overflow 上发表一个问题? - ixe013
你的代码和 OP 的更新一样有 bug。它会创建一个名为 note 的文件。 - ixe013
修复了回声重定向问题。 - Okkenator

1
批处理识别“双引号”来定界引用字符串,但不识别单引号。因此,这是括号混淆的第二章。顺便说一下 -
if defined var (echo var is defined
) else (
  echo var is not defined
)

比起if [not] "x%var%"=="x"更好

我对这个结构一直感到困惑

if not something (echo not something
 ) else (
 echo something
)

什么问题?
if something (echo something
 ) else (
 echo not something
)

如何摆脱逻辑上的体操呢?

  • 但我想这可能是风格问题,或者可能是缺乏风格...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接