如何将两个.bat文件命令合并为一个?

时间:2017-01-14 00:08:31

标签: windows batch-file

以下是我一直在使用的内容:

PING -n 1 10.0.0.1|find "Reply from" >NUL
IF NOT ERRORLEVEL 1 goto :PASS
IF     ERRORLEVEL 1 goto :FAIL

但这只有在IP匹配时才有效。

所以,我在这个网站上找到了这些命令(在Wernfried Domscheit的回答中),这些命令似乎独立工作,但我不知道如何将它们合并在一起:

在批处理文件中:

for /f "tokens=2 delims=:" %%g in ('netsh interface ip show address ^| findstr "Default Gateway"') do ping %%g

cmd提示符下:

for /f "tokens=2 delims=:" %g in ('netsh interface ip show address ^| findstr "Default Gateway"') do ping %g

有什么建议吗?

2 个答案:

答案 0 :(得分:0)

不是检查ping输出是否包含"来自"的回复,而是搜索" TTL ="

ping -n 1 10.0.0.1| findstr "TTL="

this answer所述。正在搜索" TTL =" ping之后比搜索"来自"的回复更可靠。有一些ping错误消息"来自"的回复。在某些情况下,您可以从另一台计算机获得回复,例如说明您要查找的计算机无法访问。然后,您将收到来自"的答复。在失败的ping输出中。

如果要在for循环中使用带findstr及其错误级别的ping,则不能使用goto跳转到标签。 goto会破坏你的循环上下文。您可以将goto视为一个命令,告诉解析器放弃它正在处理/执行的命令(FOR循环)并从您给出的标签开始作为参数。它只会忘记循环。

我会假设您的标签是这样排列的:

:PASS
rem some commands in case the ping succeeded
<commands_succes>
goto :BOTH

:FAIL
rem some code in case the ping failed
<commands_fail>

:BOTH
rem code that has to be executed in both cases after code for individual case (if any)
<commands_after>

您的循环可以采用以下不同的形式:

  • 使用IF ERRORLEVEL 1 ( ... ) ELSE ( )并将:FAIL标签中的所有代码移至if分支,并将:PASS标签中的所有代码移至else分支。来自:BOTH标签的代码(如果有的话)将归入整个if-block

    for /f "tokens=2 delims=:" %%g in ('netsh interface ip show address ^| findstr /C:"Default Gateway"') do (
        ping %%g | findstr "TTL=">NUL
        IF ERRORLEVEL 1 (
            rem Here comes code in case the ping failed (code for :FAIL label)
            <commands_fail>
        ) ELSE (
            rem Here comes code in case the ping succeeded (code for :PASS label)
            <commands_succes>
        )
        rem code that has to be executed in both cases after code for individual case (if any)
        <commands_after>
    )
    
  • 使用call命令而不是goto来使用函数调用。如果call命令与标签一起使用,则它与goto相同,除了解析器将记住其状态(它正在执行的命令)并且在执行标签后将返回到它退出。所以它会从标签执行命令,直到遇到明确的exitgoto :EOF或文件结尾。

    for /f "tokens=2 delims=:" %%g in ('netsh interface ip show address ^| findstr /C:"Default Gateway"') do (
        ping %%g | findstr "TTL=" > NUL
        IF ERRORLEVEL 1 (
            rem ping failed
            call :FAIL
        ) ELSE (
            rem ping succeeded
            call :PASS
        )
    )
    
    exit /b 0
    
    :PASS
    rem some commands in case the ping succeeded
    <commands_succes>
    goto :BOTH
    
    :FAIL
    rem some code in case the ping failed
    <commands_fail>
    
    :BOTH
    rem code that has to be executed in both cases after code for individual case (if any)
    <commands_after>
    exit /b 0
    

这两种情况都适合你。您只需将与<commands_fail><commands_success><commands_after>对应的代码复制粘贴到正确的位置即可。如果您在<commands_after>中没有任何内容,可以将其留空。

编辑:感谢@Josefz注意到我在FOR循环中使用的命令中遗漏了一点错误,以获取默认网关的IP地址:

netsh interface ip show address | findstr "Default Gateway"

问题是findstr使用空格作为其正则表达式的分隔符(grep = findstr运算符中的| = OR中的空格)。因此,在上述情况下,它将会Default Gateway,并且不仅会为您提供默认网关,还会为您提供网关指标。甚至是IP地址。使用/C的{​​{1}}开关查找字符串findstr

Default Gateway

我也在上面的代码示例中对其进行了更正。

祝你好运!

PS:在这两种情况下,您都可以使用conditional execution而不是检查错误级别。请点击链接获取更多信息,但请务必阅读说明!

答案 1 :(得分:0)

虽然没有明确说明,但我会假设您要使用第二个命令在第一个命令中找到的IP。这很简单:

for /f "tokens=2 delims=:" %%g in ('netsh interface ip show address ^| findstr "Default Gateway"') do SET IP=%%g
PING -n 1 %IP%|find "Reply from" >NUL
IF NOT ERRORLEVEL 1 goto :PASS
IF     ERRORLEVEL 1 goto :FAIL

您在IP语句中设置变量(for),并使用它而不是ping中的固定IP。