【问题标题】:Can I have an IF block in DOS batch file?我可以在 DOS 批处理文件中有一个 IF 块吗?
【发布时间】:2011-06-26 09:24:59
【问题描述】:

在 DOS 批处理文件中我们只能有 1 行 if 语句体?我想我在某个地方找到了可以将() 用于if 块的地方,就像在类C 编程语言中使用的{} 一样,但是当我尝试这个时它没有执行语句。也没有错误信息。这是我的代码:

if %GPMANAGER_FOUND%==true(echo GP Manager is up
goto Continue7
)
echo GP Manager is down
:Continue7

奇怪的是,当我运行批处理文件时,“GP Manager is up”和“GP Manager is down”都没有打印出来。

【问题讨论】:

  • 也许这可能会有所帮助:commandwindows.com/batchfiles-branching.htm
  • 是的,这有帮助。 DOS很烂。如果我想在 if 中使用多个语句,否则我必须在语句之间使用 &&?还是有更优雅的方式?

标签: if-statement batch-file


【解决方案1】:

您确实可以在条件之后创建一个要执行的语句块。但是您的语法错误。括号必须完全按照所示使用:

if <statement> (
    do something
) else (
    do something else
)

但是,我认为else-if 语句没有任何内置语法。不幸的是,您需要创建嵌套的 if 语句块来处理它。


其次,%GPMANAGER_FOUND% == true 测试在我看来非常可疑。我不知道环境变量设置为什么或您如何设置它,但我非常怀疑您显示的代码是否会产生您正在寻找的结果。


以下示例代码对我来说很好:

@echo off

if ERRORLEVEL == 0 (
    echo GP Manager is up
    goto Continue7
)
echo GP Manager is down
:Continue7

请注意我的示例代码的一些具体细节:

  • 在条件语句结尾和左括号之间添加的空格。
  • 我正在设置 @echo off 以防止在执行时看到所有打印到控制台的语句,而只看到那些特别以 echo 开头的语句的输出。李>
  • 我正在使用内置的ERRORLEVEL 变量作为测试。阅读更多here

【讨论】:

  • 如果 %ERRORLEVEL% == 0 更好使用,因为其他变体始终为真,因为如果 ERRORLEVEL 为真,如果 errorlevel 等于或大于 ,则“==”在这种情况下被忽略
  • @jeb:我想你可能错过了重点。使用ERRORLEVEL 不是他问题的答案。我只是发布了一个正确语法的例子。在这种情况下,Either 形式是可以接受的,就像if 0 == 0 或任何其他琐碎的表达式一样。但实际上,请确保您了解环境变量%ERRORLEVEL% 和命令处理器的内部ERRORLEVEL 之间的区别。 Raymond Chen 解释得很好here on this blog。
  • 可能值得注意的是,如果您需要在 IF 块内使用包含括号(例如C:\Program Files (x86))的路径,那么您将不得不使用延迟扩展或 IF 块一旦遇到路径中的括号就会退出,如I found out。
  • 添加到@mythofechelon 的评论中,即使是 REM 语句中看似无害的右括号也会结束该块。例如将REM This is a comment (or so I thought) 扔进IF 块会搞砸你。
  • @mythofechelon 和@rkagerer 都指出了字符串需要被引用的一般规则的具体问题。您永远不应编码IF %somevar%==example_string2,它应该始终是代码,因此操作数解析为IF "value_of_somevar"=="example_string2" 以避免任一字符串操作数中的特殊字符导致IF 语句中的语法错误。您设置的值应始终为set "somevar=value_of_somevar" 那语法允许您转义变量值中的特殊字符,请注意我的意思不是set somevar="value_of_somevar"
【解决方案2】:

从逻辑上讲,Cody 的回答应该有效。但是我不认为命令提示符在逻辑上处理代码块。在我的一生中,我只能使用块中的单个命令来使其正常工作。在我的例子中,广泛的测试表明块中的所有命令都被缓存,并在块的末尾同时执行。这当然不会产生预期的结果。这是一个过于简单的例子:

if %ERRORLEVEL%==0 (
set var1=blue
set var2=cheese
set var3=%var1%_%var2%
)

这应该为 var3 提供以下值:

blue_cheese

而是产生:

_

因为所有 3 个命令在退出代码块时都被缓存并同时执行。

我能够通过重写 if 块以仅执行一个命令 - goto - 并添加一些标签来克服这个问题。它笨重,我不太喜欢它,但至少它有效。

if %ERRORLEVEL%==0 goto :error0
goto :endif

:error0
set var1=blue
set var2=cheese
set var3=%var1%_%var2%

:endif

【讨论】:

  • 使用延迟扩展应该可以工作:使用:set var3=!var1!_!var2!
【解决方案3】:

可能有点晚了,但希望它会好起来:

@echo off 

if %ERRORLEVEL% == 0 (
msg * 1st line WORKS FINE rem You can relpace msg * with any othe operation...
goto Continue1
)
:Continue1
If exist "C:\Python31" (
msg * 2nd line WORKS FINE rem You can relpace msg * with any othe operation...
    goto Continue2
)
:Continue2
If exist "C:\Python31\Lib\site-packages\PyQt4" (  
msg * 3th line WORKS FINE rem You can relpace msg * with any othe operation...
    goto Continue3
)
:Continue3
msg * 4th line WORKS FINE rem You can relpace msg * with any othe operation...
    goto Continue4
)
:Continue4
msg * "Tutto a posto" rem You can relpace msg * with any othe operation...
pause

【讨论】:

    【解决方案4】:

    尝试使用与符号 & 或双与符号 &&(以错误级别 0 为条件)作为命令分隔符,而不是这种 go​​to 混乱。

    我用这个技巧修复了一个脚本 sn-p,总而言之,我有三个批处理文件,一个在找到已分配外部备份驱动器的字母后调用另外两个。我将第一个文件保留在主外部驱动器上,因此对其备份例程的调用工作正常,但对第二个文件的调用需要更改活动驱动器。下面的代码显示了我是如何修复它的:

    for %%b in (d e f g h i j k l m n o p q r s t u v w x y z) DO (
    if exist "%%b:\Backup.cmd" %%b: & CALL "%%b:\Backup.cmd"
    )
    

    【讨论】:

    • 这到底为什么会被否决?这正是我所需要的。
    • @GCB667 - 澄清@Louis”写了一个“答案”,与为什么IF语句不适用于原始海报的问题无关。它与“vinniejohnson”的答案有关(这也错过了原始海报问题)。
    【解决方案5】:

    我在批处理文件中与 IF 命令相关的搜索返回的结果中遇到了这篇文章,我无法抗拒有机会纠正 IF 块仅限于单个命令的误解。以下是生产 Windows NT 命令脚本的一部分,该脚本每天在我撰写此回复的机器上运行。

        if "%COPYTOOL%" equ "R" (
        WWLOGGER.exe "%APPDATA%\WizardWrx\%~n0.LOG" "Using RoboCopy to make a backup of %USERPROFILE%\My Documents\Outlook Files\*"
        %TOOLPATH% %SRCEPATH% %DESTPATH% /copyall %RCLOGSTR% /m /np /r:0 /tee
        C:\BIN\ExitCodeMapper.exe C:\BIN\ExitCodeMapper.INI[Robocopy] %TEMP%\%~n0.TMP %ERRORLEVEL%
    ) else (
        WWLOGGER.exe "%APPDATA%\WizardWrx\%~n0.LOG" "Using XCopy to make a backup of %USERPROFILE%\My Documents\Outlook Files\*"
        call %TOOLPATH%  "%USERPROFILE%\My Documents\Outlook Files\*" "%USERPROFILE%\My Documents\Outlook Files\_backups" /f /m /v /y
        C:\BIN\ExitCodeMapper.exe C:\BIN\ExitCodeMapper.INI[Xcopy] %TEMP%\%~n0.TMP %ERRORLEVEL%
    )
    

    也许两行或多行的块仅适用于 Windows NT 命令脚本(.CMD 文件),因为搜索仅限于老式批处理 (.BAT) 文件的应用程序的生产脚本目录,仅显示一个- 命令方块。由于该应用程序已进入扩展维护(这意味着我没有积极参与支持它),我不能说这是因为我不需要多条线路,还是因为我无法让它们工作。

    不管怎样,如果后者是真的,有一个简单的解决方法;将多行移动到单独的批处理文件或批处理文件子例程中。我知道后者适用于两种脚本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-10
      • 2015-07-20
      • 2017-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-21
      相关资源
      最近更新 更多