简体   繁体   中英

How to merge two .bat file commands to function as one?

Here is what I've been using:

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

But this only works if the IP matches.

So, I found these commands on this site (in an answer by Wernfried Domscheit) that seem to work on their own but I don't know how to incorporate them together:

In a Batch file:

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

At the cmd prompt:

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

Any advice?

Instead of checking if the ping output contains "Reply from", it's better to search for "TTL=":

ping -n 1 10.0.0.1| findstr "TTL="

as pointed in this answer . Searching for "TTL=" after a ping will be more reliable than searching for "Reply from". There are some ping error messages with "Reply from". In some cases you can get a reply from another machine stating that the machine you're looking for is not reachable for example. You'll then have a "Reply from" in the failed ping output.

If you want to use the ping with the findstr and its errorlevel in a for loop you cannot not use goto to jump to a label. The goto will destroy your loop context. You can see goto as a command that tells the parser to abandon the command it was processing/executing (the FOR loop) and start at the label you gave as argument. It will just forget about the loop.

I will assume your labels are arranged this way:

: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>

Your loop can then take these different forms:

  • using IF ERRORLEVEL 1 ( ... ) ELSE ( ) and move all code from the :FAIL label to the if-branch and all code from the :PASS label to the else-branch. The code from the :BOTH label (if any) will come under the whole 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> ) 
  • use function calls with the call command instead of goto . If the call command is used with labels it does the same as the goto except that the parser will remember its state (command it was executing) and will come back to it after the execution of the label is exited. so it will execute commands from the label untill an explicit exit , goto :EOF or end of file is encountered.

     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 

Both cases should work for you. You'll just have to copy-paste the code corresponding to the <commands_fail> , <commands_success> and <commands_after> on the right places. If you don't have anything in <commands_after> you can just leave it blank.

EDIT : Thanks to @Josefz who noticed a little mistake I missed in the command you use in the FOR loops to get the IP address of the default gateway:

netsh interface ip show address | findstr "Default Gateway"

The issue is that findstr uses whitespace as delimiter for its regular expressions (whitespace in findstr = | in grep = OR operator). So what it will be looking for in the case above is Default or Gateway and will not only give you the default gateway but also the gateway metric which isn't even an IP address. Use the /C switch of findstr to make it look for litteral string Default Gateway :

netsh interface ip show address | findstr /C:"Default Gateway"

I've corrected it in the code samples above as well.

Good luck!

PS: In both cases you can use conditional execution instead of checking the errorlevel. Follow the link for more info but be sure to read the note also!

Although not clearly stated, i'll assume that you want to use the IP found by your second command in the first one. That's simply:

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

You set a variable ( IP ) in the for statement, and use it instead of the fixed ip in the ping .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM