Send command results to batch variable - batch-file

I'm trying to compare an empty string to the results from a ping using FIND. I want to capture only failed ping requests.
Here's what I've tried so far:
ping -n 1 %choice% | FIND "Request" >> %request%
FOR /F "delims=" %%a in ('ping -n 1 %choice% | FIND "Request") Do #set request =%a
Once I get this to set correctly, I plan to compare request to an empty string.

Test this:
ping -n 1 %choice% | FIND "TTL=">nul && (echo pass) || (echo fail)
pause

You need to protect the pipe, and have matched quotes in the for command, and use %%:
FOR /F "delims=" %%a in ('ping -n 1 %choice% ^| FIND "Request" ') Do #set request =%%a

Related

Iterating through text file via batch script without for statement

I need a way to either not use the for statement, or find a way to break out of the looping process if a condition is met.
Here's what I have now...
for /f "delims=" %%a in ('type pclist.txt') do (
ping -n 1 %%a | findstr /i "reply" >nul 2>nul
if %errorlevel% equ 0 (
if exist "\\%%a\c$\windows\temp\installed.txt" (
echo %%a - Already installed >>results.txt
)
if not exist "\\%%a\c$\windows\temp\installed.txt" (
echo %%a - Not installed >>results.txt
)
)
ping -n 1 %%a | findstr /i "timed" >nul 2>nul
if %errorlevel% equ 0 echo %%a - No PING response >>results.txt
ping -n 1 %%a | findstr /i "transmit" >nul 2>nul
if %errorlevel% equ 0 echo %%a - PING transmit failed >>results.txt
)
This gives me this kind of result...
192.168.144.1 - Already installed
192.168.144.1 - No PING response
192.168.144.1 - PING transmit failure
192 168.144.2 - Already installed
192.168.144.2 - No PING response
192.168.144.2 - PING transmit failure
192.168.144.3 - Not installed
192.168.144.3 - No PING response
192.168.144.3 - PING transmit failure
What I'd like to do is be able to exit the for loop when whatever first condition is met. So, I would have this kind of result instead...
192.168.144.1 - Already installed
192 168.144.2 - Already installed
192.168.144.3 - Not installed
I'm hoping I'm simply overlooking something simple and this will be just another one of those I-D-10-T errors for me. (lol)
Thanx in advance.
In plain English. Here's the goal:
Using FOR command, read list of IP addresses from text file.
For each IP address read, PING and check response.
If PING returns a reply, check for existence of file.
If file exists,
ECHO value 1 to results file, end FOR loop, proceed with next IP address in list.
If file does not exist,
ECHO value 2 to results file, end FOR loop, proceed with next IP address in list.
If PING does not return a reply, ECHO PING error text to results file, end FOR loop, proceed with next IP address in list.
I hope that's a bit more understandable.
Thanx again.
To avoid nested IF/Else code blocks you should use subs with calls. The use of C:\windows\temp might also be a problem when redirected to C:\Users\%USERNAME%\AppData\Local\Temp. TTL is a better indicator for the ping - less depending on the locale.
#Echo off
Set Res=^>^>Results.txt
Echo %date% %time% %Res:~1%
Set Inst=Windows\temp\installed.txt
for /f "delims=" %%a in ('type pclist.txt') do Call :TestPC %%a
Type %Res:~2%
Goto :Eof
:TestPC
ping -n 1 -w 500 %1|findstr "TTL">nul 2>&1||(Call :Check %1 &Goto :Eof)
:: A rights Problem might exist
if exist "\\%1\c$\%Inst%" echo %1 - Already installed %Res%
if not exist "\\%1\c$\%Inst%" echo %1 - Not installed %Res%
Goto :Eof
:Check
ping -n 1 -w 500 %1 | findstr /i "timed" >nul 2>nul
if %errorlevel% equ 0 %Res% echo %1 - No PING response
ping -n 1 -w 500 %1 | findstr /i "transmit" >nul 2>nul
if %errorlevel% equ 0 %Res% echo %1 - PING transmit failed
Goto :Eof
returns this output
Mi 10/26/2016 17:46:35,78
192.168.3.91 - Not installed
192.168.3.95 - No PING response
192.168.3.92 - Already installed
if %errorlevel% equ 0 (
(used multiple times) - %errorlevel% refers to the value of errorlevel at the time the FOR is parsed not at run-time. You need to substitute
if not errorlevel 1
in each case to provide the required functionality (if run-time errorlevel is not (1 or greater))
Hence, you "sample current output" is bogus - you cannot get that output with the code you've shown as %errorlevel% will not change with each loop. Furthermore, your sample shows "failure" whereas you code specifies "failed".
What do you mean by whatever first condition is met ? You could get your proposed output by simply removing or commenting-out the 4 lines following the closure of your if statement.

Batch script with nested loops to ping range of IP's

Working 1 loop code:
for /l %i in (1,1,254) do #ping 131.212.30.%i -n 1 -w 100 | find "Reply"
Not running code where I try to use a counter so every time the ping gets a reply we add 1 to online:
SET online=0 for /L %i in (1,1,254) do for /L %j in (1,1,255) do #ping 131.212.%i.%j -n 1 -w 100 | find "Reply" SET /A online=online+1
Thanks a lot.
Reply from 146.57.239.18: Destination host unreachable
The destination is not reachable, so your local host (146.57.239.18) replies with "Destination host unreachable").
146.57.239.18 is not the pinged host, but your localhost.
It's better to search for TTL= instead of Reply:
...
ping 131.212.%%i.%%j -n 1 -w 100 | find "TTL="
...
Also your set /a online=%online%+1 doesn't work. You would need delayed expansion. The set /a online +=1 syntax works better:
...
ping 131.212.%%i.%%j -n 1 -w 100 | find "TTL=" && SET /A online +=1 || set /a offline +=1
...
As a result, the whole code would look like:
SET online=0
for /L %%i in (1,1,254) do for /L %%j in (1,1,255) do ping 131.212.%%i.%%j -n 1 -w 100 | find "TTL=" && SET /A online +=1
echo %online% hosts are online.
EDIT a much quicker solution (working parallel):
#echo off
SET online=0
for /L %%i in (1,1,254) do (
start /min "pinging" cmd /c "(#for /L %%j in (1,1,255) do #ping 146.254.%%i.%%j -n 1 -w 100 | find "TTL=") >ping%%i.txt"
)
:loop
timeout /t 1 >nul
tasklist /v | find "pinging" && goto :loop
pause
for /f %%i in ('type ping*.txt 2^>nul^|find /c "TTL="') do echo %%i hosts are online
del ping*.txt
You have the syntax slightly wrong. The following should work (split over a couple of lines for readability:
for /l %%i in (1,1,254) do (
for /l %%j in (1,1,254) do (
ping 131.212.%%i.%%j -n 1 -w 100 | find "Reply"
)
)
Keep in mind that this is a lot of IPs to ping.

Batch check reachable machines

I have used several scripts posted in this forum unsuccesfully.
Script is as follows:
#echo off
for /f %%i in (computersTest.txt) do (
ping -n 1 %%i | find "TTL" >nul 2>nul
Echo %errorlevel%
)
Errorlevel is always 0 no matter if host is reachable or not. If I remove the >nul to see the output I get the following
Reply from 10.6.4.20: bytes=32 time<1ms TTL=64
0
0
Reply from 10.6.5.58: bytes=32 time<1ms TTL=126
0
Where the second host in the list is not reachable but errolevel is 0
If I execute in the command prompt
ping -n 1 XXXXXXXXX | find "TTL" >NUL 2>NUL
echo %errorlevel%
gives 1
I don't know what I am doing wrong
TIA
Ramon
Batch lines or blocks of lines (lines enclosed in parenthesis) are first parsed and then executed. During the parse phase, all read operations on variables are removed from code, replaced with the value inside the variable before starting to execute the line/block. So, if a variable is changed inside a line/block, this new value can not be retrieved from inside the same line/block, as there is not a read operation to retrieve the new value.
You can solve it using delayed expansion and changing (where needed) the syntax from %var% into !var!, to indicate to the parser that the read operation must be delayed until the command executes
In your case
#echo off
setlocal enabledelayedexpansion
for /f %%i in (computersTest.txt) do (
ping -n 1 %%i | find "TTL=" >nul 2>nul
Echo %%i - !errorlevel!
)
note: The correct test in ipv4 for response is to search for TTL=, as you can have a false positive in case of a TTL expired error.
But in the case of checking the errorlevel variable, there are more alternatives (if they are applicable).
You can use the native if errorlevel n where the condition will be evaluated to true for any errorlevel equal or greater than n
#echo off
for /f %%i in (computersTest.txt) do (
ping -n 1 %%i | find "TTL=" >nul 2>nul
if errorlevel 1 ( echo %%i offline ) else ( echo %%i online )
)
Or you can use conditional execution. The operators && and || will allow to include what to execute depending on the errorlevel (not set or set) from previous command
#echo off
for /f %%i in (computersTest.txt) do (
( ping -n 1 %%i | find "TTL=" >nul 2>nul ) && echo %%i online || echo %%i offline
)

Separate IP from text in ping output?

I'd like to be able to run a single batch file that would find the IP address of every device connected to my router, and then find their hostnames from it. What I have so far is below:
#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">>devices.txt
if %n% lss 254 goto repeat
type devices.txt
goto :hostname
This finds all the possible addresses and writes them to a text file, devices.txt.
However, I now end up with the following:
Reply from 192.168.1.82: bytes=32 time=5ms TTL=255
The next part of the batch file goes:
:hostname
ping -a %ip% -l 1 -n 1 >> hostnames.txt
This pings the IPs found in devices.txt and returns the result in hostnames.txt - or at least, I'd like it to.
Somehow I need to separate the IP address from the other text when writing it to devices.txt, and then assign it as a variable so it can be used by the next part.
Is there a simple function I can use to do either of these things?
Try this:
#echo off
setlocal
set "p=ping -n 1 -w 500 192.168.1"
for /l %%a in (1,1,254) do (
for /f "Tokens=3 delims=: " %%b in (
'%p%.%%a^|Find /i "TTL="'
) do (
echo Pinging %%b
echo %%b>>devices.txt
for /f "tokens=2" %%c in (
'ping -a %%b -l 1 -n 1^|Find /i "pinging"') do (
echo %%c >>hostnames.txt
)
)
)
We start by creating a For /L loop that goes from 1 to 254 in increments of 1. Then we run a for loop on a ping command that takes the third token on the return line and puts it into a variable, %%b in this case. We then echo out pinging IP address contained in %%b and write it to devices.txt. Then, we run another ping to extract the second token which is the hostname of the computer we're pinging and write it out to hostnames.txt.

batch file - getting ip from ping command

i have this command.
ping -n 1 piratelufi.com | find /i "reply from"
i want to get the ip inside the ping response. i thought of using %var:~0,10% but i have no idea how to redirect the output to echo.
i even tried to use pipe
ping -n 1 piratelufi.com | find /i "reply from" | echo %1
but the %1 variable does not represent the output of the first two commands. i even tried to use &1 but i failed. What is the 'variable' needed to echo out the output from the first two commands?
Check out the FOR command it's really cool:
FOR /f "tokens=1,3 delims=: " %%A IN ('ping -n 1 piratelufi.com') DO IF %%A==Reply ECHO IP IS %%B
Try the following:
for /f "tokens=2 delims=[]" %f in ('ping -4 -n 1 piratelufi.com ^|find /i "pinging"') do echo IP=%f

Resources