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

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.

Related

CMD: search IP's of devices with special MAC

I need to find IP of device or devices in local network. I only know that their MAC address should start with "xx-xx-xx-xx-". I found following script that do almost what I need:
#echo off
:top
:: Loop through arp table entries and look for my device's MAC address
for /f "tokens=1-5 skip=3" %%f in ('arp -a') do (
if "%%g"=="xx-xx-xx-xx-xx-xx" set ip=%%f
)
if "%ip%"=="" (
echo Discovering network...
:: Ping all IPs from 192.168.0.1 to 254
for /L %%N in (1,1,254) do start /b ping -n 1 -w 200 192.168.0.%%N >nul
timeout 1 >nul
goto :top
) else (
echo Device found found: %ip%
)
pause
But this script search only with full MAC and only one device. How make it search subMAC and several devices?
the following works for me:
#echo off
:top
:: Loop through arp table entries and look for my device's MAC address
set "ip="
for /f "tokens=2" %%f in ('arp -a^|find " d4-85-64"') do set ip=%%f
if "%ip%"=="" (
echo Discovering network...
:: Ping all IPs from 192.168.0.1 to 254
for /L %%N in (1,1,254) do start /b ping -n 1 -w 200 192.168.0.%%N >nul
timeout 1 >nul
goto :top
)
echo Device found: %ip%
pause
Changes:
set "ip=" to empty variable (in case, it already exists (from previous run))
removed skip (not needed),
set "tokens=2" (that's all, we need)
included find " xx-xx-xx" to search the desired line (with leading space for "start with") (of course I choosed a MAC existing in MY network)
moved success message out of if (not neccesary, but cleaner code)

Batch file 'continue' to next iteration in FOR loop

I'm currently supporting a team of techs who are upgrading machines in offices and I need to keep track of the amount of machines that are online.
Currently what I have is a text file (OfficeName.txt) with a list of machine names, and a batch file (OfficeName.bat).
What I want to happen is for it to loop through the list of machines and ping them.
If the ping is successful, remove the name from the list and increment a counter by 1, if unsuccessful, then move on to the next machine in the list.
The issue I'm having is that if a machine's ping result comes back with "could not find host", it still sets the errorlevel to 0, so I can't use an IF/ELSE.
My current attempt looks like this:
#echo off
setlocal EnableDelayedExpansion
set /a counter=0
set "NVC="
for /F %%a in (%~n0.txt) do set "NVC=!NVC! %%a"
:ping
for %%i in (%NVC%) do (
ping %%i -n 1 >nul | find "TTL=" >nul || echo. %%i is offline.
set /a counter+=1
echo %%i is online
set "NVC=!NVC: %%i=!"
)
cls
echo. %counter% machines are online.
if defined NVC goto :ping
echo All machines in %~n0 are online.
pause
The problem is that once the "%%i is offline" line is done, it just continues to the next line and removes it anyway.
Is there a way to skip the 3 lines below the ping if the ping result is bad, and continue with the next iteration in the list?
Note: I'm running this from Server 2008, pinging Win 8.1 machines.
Your first problem is that you're trying to find "TTL=" in output that's been redirected to NUL. Remove that redirection so FIND gets something to search.
Your second problem is a logic error, where even if you execute the || clause, the other lines are executing too. You need to use an ELSE or another IF clause.
Finally, I think you're overcomplicating the processing of your list of IP addresses.
Try this, and see if it makes sense.
#echo off & setlocal
set /a counteron=0
set /a counteroff=0
for /f %%i in (%~n0.txt) do (
ping %%i -n 1 | find "TTL=" >nul
if errorlevel 1 (
set /a counteroff+=1
echo %%i is offline.
) else (
set /a counteron+=1
echo %%i is online
)
)
echo.
echo %counteron% machines are online.
echo %counteroff% machines are offline.

How do I ping the default gateway without specifying the IP address?

I'm trying to write a batch file that tests network connectivity by pinging the default gateway of the given network.
However, as I want this to be an automated process which then logs the results to a text file, I'd like to be able to ping the gateway on various networks, without having to change/enter the ip address.
Is there a generic term or command to ping the default gateway for the network you're currently connected to?
(I already have the commands for output options etc.)
So far, I have this....
#echo off
goto :NETWORK1
:NETWORK1
ipconfig
echo .
Set /P gateway=PLEASE ENTER GATEWAY IP ADDRESS (shown above):
if /I "%gateway%" EQU "exit" goto :EXIT
if /I not "%gateway%" EQU "exit" goto :NETWORK2
:NETWORK2
echo CLOSING THIS WINDOW WILL ABORT THE CONNECTIVITY TEST.
echo . >> "C:\Network Test Results %date:/=.%.txt"
echo Time: >> "C:\Network Test Results %date:/=.%.txt"
time /t >> "C:\Network Test Results %date:/=.%.txt"
ping %gateway% -n 20 >> "C:\Network Test Results %date:/=.%.txt"
goto :NETWORK2
:EXIT
exit
But I don't want to have to specify the IP address, so that I can take away the need for user input.
smalll fix for Wernfried Domscheit
for /f "tokens=2 delims=:" %%g in ('netsh interface ip show address ^| findstr /c:"Default Gateway"') do ping %%g
pause
just adding /c: before "Default Gateway"
On a command line you can try this one:
for /f "tokens=2 delims=:" %g in ('netsh interface ip show address ^| findstr "Default Gateway"') do ping %g
Note, inside a batch-file you must double the %, i.e.
for /f "tokens=2 delims=:" %%g in ('netsh interface ip show address ^| findstr "Default Gateway"') do ping %%g
According to jimbobomcgee on serverfault who phrased the correct answer for the question How to Extract command-line output into a Variable?
for /f "usebackq tokens=1,2,3 delims=:" %A in (`ipconfig ^| Find "Default Gateway" ^| Findstr/N "." ^| Findstr/B "1:"`) do #if not defined MYVAR set MYVAR=%~C
#echo off
setlocal enableextensions disabledelayedexpansion
set "gateway="
for /f "tokens=1-5" %%a in ('route -4 print 0.*') do #if "%%e"=="" if "%%a"=="%%b" set "gateway=%%c"
if not defined gateway goto :eof
echo CLOSING THIS WINDOW WILL ABORT THE CONNECTIVITY TEST.
:loop
echo %date% %time%
>> "Network Test Results %date:/=.%.txt" (
echo(
echo(Time: %time%
ping -n 20 -4 %gateway%
)
goto :loop
Gateway determination from route information copied from here
edited for a more tolerant parse of the route command use
for /f "tokens=3" %%a in ('route -4 print 0.* ^| find "0."') do set "gateway=%%a"
After help from #MC ND, I have created the following code, which does exactly what I needed....
pings the default gateway with the results being output to a text file
shows a message telling the user not to close the command window
#echo off
setlocal enableextensions disabledelayedexpansion
for /f "tokens=3" %%a in ('route -4 print 0.*') do set "gateway=%%a"
:NETWORK
echo CLOSING THIS WINDOW WILL ABORT THE CONNECTIVITY TEST.
echo Time >> "C:\Network Test Results %date:/=.%.txt"
time /t >> "C:\Network Test Results %date:/=.%.txt"
echo . >> "C:\Network Test Results %date:/=.%.txt"
ping %gateway% -n 20 >> "C:\Network Test Results %date:/=.%.txt"
goto :NETWORK

Ping all addresses in network, windows

Is it possible in windows cmd line to check all of the network addresses (with ping or similar) to see which ones are taken/ have active devices:
ie. something that does something like the following:
for i = 0 to 255
ping 192.168.1.i //Print this
end
This is psuedo code obviously. I am wondering if it is possible to do something like this in windows cmd. It would be great if you didn't need a batch file, but i understand if this is impossible.
PS. Also please mention if there is a program to do this, but it would be nice to do it in cmd.
Open the Command Prompt and type in the following:
FOR /L %i IN (1,1,254) DO ping -n 1 192.168.10.%i | FIND /i "Reply">>c:\ipaddresses.txt
Change 192.168.10 to match you own network.
By using -n 1 you are asking for only 1 packet to be sent to each computer instead of the usual 4 packets.
The above command will ping all IP Addresses on the 192.168.10.0 network and create a text document in the C:\ drive called ipaddresses.txt. This text document should only contain IP Addresses that replied to the ping request.
Although it will take quite a bit longer to complete, you can also resolve the IP Addresses to HOST names by simply adding -a to the ping command.
FOR /L %i IN (1,1,254) DO ping -a -n 1 192.168.10.%i | FIND /i "Reply">>c:\ipaddresses.txt
This is from Here
I know this is a late response, but a neat way of doing this is to ping the broadcast address which populates your local arp cache.
This can then be shown by running arp -a which will list all the addresses in you local arp table.
ping 192.168.1.255
arp -a
Hopefully this is a nice neat option that people can use.
Best Utility in terms of speed is Nmap.
write # cmd prompt:
Nmap -sn -oG ip.txt 192.168.1.1-255
this will just ping all the ip addresses in the range given and store it in simple text file
It takes just 2 secs to scan 255 hosts using Nmap.
Provided the windows box is in the same subnet:
for /L %a in (1,1,254) do start ping 192.168.0.%a
This will complete in less than 15 seconds and
arp -a
will return any alive host.
Fastest native way I know of in Windows.
This post asks the same question, but for linux - you may find it helpful. Send a ping to each IP on a subnet
nmap is probably the best tool to use, as it can help identify host OS as well as being faster. It is available for the windows platform on the nmap.org site
An expansion and useful addition to egmackenzie's "arp -a" solution for Windows -
Windows Example searching for my iPhone on the WiFi network
(pre: iPhone WiFi disabled)
Open Command Prompt in Admin mode (R.C. Start & look in menu)
arp -d <- clear the arp listing!
ping 10.1.10.255 <- take your subnet, and ping '255', everyone
arp -a
iPhone WiFi on
ping 10.1.10.255
arp -a
See below for example:
Here is a nice writeup on the use of 'arp -d' here if interested -
TechRepublic - Quick Tips Flush the ARP cache in Windows 7
All you are wanting to do is to see if computers are connected to the network and to gather their IP addresses. You can utilize angryIP scanner: http://angryip.org/ to see what IP addresses are in use on a particular subnet or groups of subnets.
I have found this tool very helpful when trying to see what IPs are being used that are not located inside of my DHCP.
Some things seem appeared to have changed in batch scripts on Windows 8, and the solution above by DGG now causes the Command Prompt to crash.
The following solution worked for me:
#echo off
set /a n=0
:repeat
set /a n+=1
echo 192.168.1.%n%
ping -n 1 -w 500 192.168.1.%n% | FIND /i "Reply">>ipaddresses.txt
if %n% lss 254 goto repeat
type ipaddresses.txt
aping can provide a list of hosts and whether each has responded to pings.
aping -show all 192.168.1.*
#ECHO OFF
IF "%SUBNET%"=="" SET SUBNET=10
:ARGUMENTS
ECHO SUBNET=%SUBNET%
ECHO ARGUMENT %1
IF "%1"=="SUM" GOTO SUM
IF "%1"=="SLOW" GOTO SLOW
IF "%1"=="ARP" GOTO ARP
IF "%1"=="FAST" GOTO FAST
REM PRINT ARP TABLE BY DEFAULT
:DEFAULT
ARP -a
GOTO END
REM METHOD 1 ADDRESS AT A TIME
:SLOW
ECHO START SCAN
ECHO %0 > ipaddresses.txt
DATE /T >> ipaddresses.txt
TIME /T >> ipaddresses.txt
FOR /L %%i IN (1,1,254) DO ping -a -n 2 192.168.%SUBNET%.%%i | FIND /i "TTL=" >> ipaddresses.txt
GOTO END
REM METHOD 2 MULTITASKING ALL ADDRESS AT SAME TIME
:FAST
ECHO START FAST SCANNING 192.168.%SUBNET%.X
set /a n=0
:FASTLOOP
set /a n+=1
ECHO 192.168.%SUBNET%.%n%
START CMD.exe /c call ipaddress.bat 192.168.%SUBNET%.%n%
IF %n% lss 254 GOTO FASTLOOP
GOTO END
:SUM
ECHO START SUM
ECHO %0 > ipaddresses.txt
DATE /T >> ipaddresses.txt
TIME /T >> ipaddresses.txt
FOR /L %%i IN (1,1,254) DO TYPE ip192.168.%SUBNET%.%%i.txt | FIND /i "TTL=" >> ipaddresses.txt
FOR /L %%i IN (1,1,254) DO DEL ip192.168.%SUBNET%.%%i.txt
type ipaddresses.txt
GOTO END
:ARP
ARP -a >> ipaddresses.txt
type ipaddresses.txt
GOTO END
:END
ECHO DONE WITH IP SCANNING
ECHO OPTION "%0 SLOW" FOR SCANNING 1 AT A TIME
ECHO OPTION "%0 SUM" FOR COMBINE ALL TO FILE
ECHO OPTION "%0 ARP" FOR ADD ARP - IP LIST
ECHO PARAMETER "SET SUBNET=X" FOR SUBNET
ECHO.
#echo off
if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b)
arp -d
setlocal
setlocal enabledelayedexpansion
for /f "usebackq tokens=*" %%a in (`ipconfig ^| findstr /i "192"`) do (
for /f delims^=^:^ tokens^=2 %%b in ('echo %%a') do (
for /f "tokens=1-4 delims=." %%c in ("%%b") do (
set _o1=%%c
set _o2=%%d
set _o3=%%e
set _o4=%%f
set _3octet=!_o1:~1!.!_o2!.!_o3!.
for /L %%a in (1,1,254) do start /min ping /n 1 /l 1 !_3octet!%%a
)))
endlocal
After you run the batch file, type this command
arp -a
All devices connected to the network will be displayed
for /l %%a in (254, -1, 1) do (
for /l %%b in (1, 1, 254) do (
for %%c in (20, 168) do (
for %%e in (172, 192) do (
ping /n 1 %%e.%%c.%%b.%%a>>ping.txt
)
)
)
)
pause>nul

Batch ping a list of computer names and write the results to file

The code below will write the computer name and ip address to file, but I would like it to also write the name of the computers it cannot ping with a fail next to it. I have no idea how I would modify the batch file to do this.
#echo off
Echo Pinging list...
set ComputerList=list.txt
Echo Computername,IP Address>Final.csv
setlocal enabledelayedexpansion
for /f "usebackq tokens=*" %%A in ("%ComputerList%") do (
for /f "tokens=3" %%B in ('ping -n 1 -l 1 %%A ^|findstr Reply') do (
set IPadd=%%B
echo %%A,!IPadd:~0, -1!>>Results.csv
))
pause
You could use errorlevel set by findstr to substitute return string(s) if 'Reply' is not found:
('ping -n 1 -l 1 %%A ^|findstr Reply ^|^| echo Not found Failed:')
where || (escaped here because of for context with ^) means execute only if previous command failed.
As a side note, you should be aware that ping messages are system language dependent (they are translated to language of OS) so 'Reply' as success indicator works only for English versions.
This may not be directly what you are looking for, but I had a similar task: run ping and report success or failure. I'll leave extracting the IP address to you - seeing as you have already done it.
The problem with ping is that it returns success upon name resolution, whether packets get lost or host is unreachable (will report 0% Loss) is irrelevant.
FOR %%a IN (
google.com
a.b.c.d
) DO #FOR /F "delims=" %%p IN (
'PING -w 100 -n 1 %%a ^| findstr ^"Reply Request fail name^"'
) DO #(
ECHO "%%p" | FINDSTR TTL >2 && echo %%a, success, %%p || echo %%a, failed, %%p
) >> Results.csv
Logic: Ping once, filter only lines with the one of the words listed. If TTL exists in resulting line (output to STDERR or NUL to avoid output pollution) echo success, else echo failed.
I'm on English Windows, words will have to be adjusted for other languages.
EDIT:
FOR %%a IN (
google.com
a.b.c.d
) DO #FOR /F "delims=" %%p IN ('PING -n 1 %%a ^| findstr TTL ^|^| echo Failed') DO #(
ECHO "%%p" | FINDSTR TTL >2 && (for /f "tokens=3" %%b IN ("%%p") do #echo %%a, %%b) || echo %%a, failed, %%p
)
Less dependant on language, works only for IPv4, added IP extraction.
Filter ping output for TTL, set output to "Failed" if TTL not found.
If output string contains TTL, extract IP and echo host and IP, else echo host name and output string.

Resources