Single Line FOR /F command FINDSTR error handling unexpected results - batch-file

Problem defined is to have a command line that takes the output of nslookup from a FOR /F loop and either sends to the IP Address to a text file or sends a error message.
The simplest iteration I have is:
FOR /F "skip=3 usebackq tokens=1*" %a IN (`^"nslookup ADROOT02.adroot.the-server-company.co.za 2^>^&1^"`) DO #echo %a | findstr /C:"Address" >nul 2>&1 && echo found || echo not found
However, this only works if an address is found, but no output is received if the findstr fails; i.e. no || echo not found is not activated for some reason.
I am looking for assistance is finding the issue/resolution to have a single command line executable that can define the IP addresses.

#ECHO OFF
SETLOCAL
FOR %%d IN (google.com ADROOT02.adroot.the-server-company.co.za ) DO (
NSLOOKUP %%d 2>&1|FIND "Non-existent domain" >nul&IF ERRORLEVEL 1 (ECHO %%d found) ELSE (ECHO %%d NOT found)
)
GOTO :EOF
Yields
google.com found
ADROOT02.adroot.the-server-company.co.za NOT found
for me.

With guidance from this forum I was able to put a command together that outputs the IP address from nslookup or error if no IP found:
FOR /F "usebackq tokens=1* delims=: " %a IN (`^"nslookup server-company.co.za 2^>^&1` ^| findstr ^/N ^/C^:^"Address^" 2^>^&1 ^"`) DO IF %a GTR 3 ( SET res2=%b & echo %res2:~10%) ELSE (echo ERROR)

Related

Only run code when connected to wifi Batch

I need to run a batch file only if it's connected to Wifi and specifically not Bluetooth LAN
I have this code but it returns this and still runs the code while an internet connection isn't present
Node - DEVICENAME
ERROR:
Description = Invalid query
Code:
#echo off
For /f "usebackq" %%A in (
`wmic path WIN32_NetworkAdapter where 'NetConnectionID="Wi-Fi"' get NetConnectionStatus`
) do if %%A equ 7 (goto end)
<code to run>
:end
You don't need a for loop:
wmic path WIN32_NetworkAdapter where 'NetConnectionID="Wi-Fi"' get NetConnectionStatus |find "7" >nul && goto :eof
echo code to run
If you want to make it more secure, instead of find "7" use findstr /rc:"^7 *$"
(your original approach fails because the = has to be escaped: ... where 'NetConnectionID^="Wi-Fi"' get ... and due to the unusual wmic output, there are CR in your %%A, which messes up the if syntax; You can see both issues with echo on (at least you can see that strange things happen))
The output of WMIC is also the reason for that strange findstr pattern, I used. (there are trailing spaces after the 7).
If you don't already know the name of the wireless interface connection, (which is a configurable property), then you could probably use something more like this:
#For /F Tokens^=6^ Delims^=^" %%G In ('%SystemRoot%\System32\wbem\WMIC.exe NIC
Where "Not NetConnectionID Is Null And NetConnectionStatus='2'" Get
NetConnectionID /Format:MOF 2^>NUL') Do #%SystemRoot%\System32\netsh.exe WLAN^
Show Interfaces 2>NUL | %SystemRoot%\System32\findstr.exe /E /L ": %%G" 1>NUL^
&& <code to run>
If your target systems are still using Windows 7, (which has a known issue locating some of the XSL files used in the /Format option), then the following alternative may work for you:
#For /F "Skip=1 Delims=" %%G In ('%SystemRoot%\System32\wbem\WMIC.exe NIC Where
"Not NetConnectionID Is Null And NetConnectionStatus='2'" Get NetConnectionID
2^>NUL') Do #For /F "Tokens=*" %%H In ("%%G") Do #%SystemRoot%\System32\netsh.exe^
WLAN Show Interfaces 2>NUL | %SystemRoot%\System32\findstr.exe /E /L ": %%H" 1>NUL^
&& <code to run>
You would obviously change your provided, and replicated above, <code to run>, to one or more actual valid commands

Pinging Multiple Computers IF Statement

I'm trying to create a little batch file that checks multiple PCs read from a text file. For any PCs it finds are pingable, it writes a line in a "results" text file saying so. Here's what I've got:
#Echo off
set file=C:\logs\registercheck.txt
date /t >%file%
FOR /F %%I IN (C:\work\regnames.txt) DO (ping /n 1 %%I | ping /n 1 %%I | IF errorlevel 1 goto :nextreg | echo %%I is still on and has not been powered off! >>%file% | :nextreg)
PAUSE
So...when I run the file, I get multiple lines of "goto was unexpected at this time" and the only thing written in my output text file is the date. What am I doing wrong?
Thank you!
#Echo off
setlocal enableextensions disabledelayedexpansion
set "logFile=C:\logs\registercheck.txt"
set "inputFile=C:\work\regnames.txt"
>>"%logFile%" date /t
for /f "usebackq delims=" %%i in ("%inputFile%") do (
ping -n 1 %%i >nul 2>nul
if not errorlevel 1 (
>>"%logFile%" echo(%%i is still on and has not been powered off!
)
)
You have two errors.
The first is that to put all the commands in a single line, the separator is not the pipe character (|) but the ampersand (&)
The second is that inside the do code block of the for command, if one goto is executed, the for command is finished, independently of where the label is placed. And labels inside for code blocks usually generate errors (depends of its position).
If instead of the previous code, you want a single line loop, it can be written as
for /f "usebackq delims=" %%i in ("%inputFile%") do ( ping -n 1 %%i >nul 2>nul & if not errorlevel 1 >>"%logFile%" echo(%%i is still on and has not been powered off! )
or
for /f "usebackq delims=" %%i in ("%inputFile%") do ( ping -n 1 %%i >nul 2>nul && >>"%logFile%" echo(%%i is still on and has not been powered off! )
that makes use of the && construct. It is intended as a shortcut for the if not errorlevel 1 .... If the command at the left of the && does not raise an errorlevel, then the command on the right side is executed.
This for the batch sintax. Now the ping. There is a difference in how ping command behaves depending of the ip version. It is not the same to ping an ipv4 address than to ping an ipv6 address. If needed you can grab from here a subrotine to handle the differences.

Reading out put of previous command in bat command file

I am very new to batch programming, I am trying to write a batch file that is a fake virus. I need to obtain the IP address from the previous command IPCONFIG into the variable VarIP. Can you help me?
My code:
echo off
echo Trying to hack your computer
ipconfig
echo Now hacking your IP
ping -t VarIP
echo on
pause
It's pretty simple to extract part of the output from any console command by using find to eliminate the lines in the output that you do not want, then using the for command to extract a portion of the line found by find:
#echo off
setlocal ENABLEDELAYEDEXPANSION
for /f "tokens=2 delims=:" %%i in ('ipconfig ^| find /i "IPv4 Address"') do (set VarIP=%%i&set VarIP=!VarIP: =!)
ping -t !VarIP!
endlocal
Hopefully you are just creating a practical joke on a friend and aren't up to anything more nefarious.
Another Version without "Tokens" for NT :
setlocal enabledelayedexpansion
for /f "delims=" %%a in ('ipconfig ^| find /i "IPv4 Address"') do (set VarIP=!%%a%!)
ping -t %VarIP%
This is a useful method to get IP info:
#echo off
for /f "tokens=2,3 delims={,}" %%a in ('"WMIC NICConfig where IPEnabled="True" get IPAddress /value | find "I" "') do echo IPv4 %%~a IPV6 %%~b
pause

Not able to read a line containing ) (closing bracket) through a batch script

My text file contains the following lines:
;
; TEST (C)kary global parameters file
;
;===================================================================
; Test servers list
;===================================================================
TC_SERVER_NAME test123
TC_SERVER_TITLE Tc_test
I am using the following lines of code to read the lines and get the TC_SERVER_NAME line.
FOR /f tokens^=*^ eol^= %%C IN (%TEST_FILE%) do
(
echo %%C | findstr /i "TC_SERVER_NAME" >nul:
if "%errorlevel%"=="0" (
echo %%C >> %OUTFILE%
)
)
However, I get the following error while executing this code.
"kary was unexpected at this time"
However, if I remove the ")" before kary from the text file, the script executes fine and I get the desired results.
So what is wrong with this ")" over here. Is it treating the ")" as some command here? How do I resolve this issue?
The code and sample you posted, isn't responsible for the error.
There are only two obviously bugs, the opening bracket must be on the same line as the FOR/F and the redirection to >nul: should be only >nul.
It doesn't output anything, but it doesn't result in an error message.
The if statement can't work, as the expansion of %errorlevel% is done when the complete block is parsed, not when it is executed.
Foxidrives solution should solve this.
Or you can try this
findstr /i "TC_SERVER_NAME" %TEST_FILE% > %OUTFILE%
Does this help?
FOR /f tokens^=*^ eol^= %%C IN (%TEST_FILE%) do (
echo %%C | findstr /i "TC_SERVER_NAME" >nul
if "%errorlevel%"=="0" >> %OUTFILE% echo %%C
)
You probably want this though:
#echo off
set test_file=source.txt
set outfile=out.txt
FOR /f tokens^=*^ eol^= %%C IN (%TEST_FILE%) do (
echo %%C | findstr /i "TC_SERVER_NAME" >nul && >> %OUTFILE% echo %%C
)
#jeb last solution is simpler and best, however I would like to introduce you &&, so your batch would be
FOR /f "tokens=* eol=" %%C IN (%TEST_FILE%) do echo %%C | findstr /i "TC_SERVER_NAME" >nul && echo %%C >> %OUTFILE%
However, this is very unsafe, as text may contain (, <, &, |, ", > characters, which will modify command behavior. Use #jeb solution, instead of FOR and everything else. Is safer and faster!
it works with enabledelayedexpanson:
(I "hardcoded" the input- and output-file for testing)
#echo off
setlocal enabledelayedexpansion
FOR /f "tokens=* eol=" %%C IN (t.t) do (
echo %%C | findstr /i "TC_SERVER_NAME" >nul:
if "!errorlevel!"=="0" ( echo %%C >> o.o )
)

How to ping multiple servers and return IP address and Hostnames using batch script?

So I have to use batch only for this. Basically, the server HOSTNAMES are all listed in a txt file. I used the following code to ping all the servers and display their results in a txtfile.
For /f %%i in (testservers.txt) do ping -n 1 %%i >>pingtest.txt
The above pinged all the servers. Now, I want to output the IP addresses and the HOST Names in a separate file. How can I do this?
I know that I can run a for loop searching for words like "TTL" and then look for the 3rd token (for the IP) and words like "PINGING" for the second token(HOSTNAME). But I am having errors and cant display it properly. The reason why I want to output IPs and Hostnames in a different file is to make a list of the DOWN and UP servers.
Help will be appreciated. :)
EDIT: Just so it isn't confusing, wanted to let you guys know there are 3 different files, testservers.txt has the HOSTNAMES in it, pingtest.txt has ping results, and result.txt will have the IPs along with Hostnames with their current status as DOWN or UP.
Well, it's unfortunate that you didn't post your own code too, so that it could be corrected.
Anyway, here's my own solution to this:
#echo off
setlocal enabledelayedexpansion
set OUTPUT_FILE=result.txt
>nul copy nul %OUTPUT_FILE%
for /f %%i in (testservers.txt) do (
set SERVER_ADDRESS=ADDRESS N/A
for /f "tokens=1,2,3" %%x in ('ping -n 1 %%i ^&^& echo SERVER_IS_UP') do (
if %%x==Pinging set SERVER_ADDRESS=%%y
if %%x==Reply set SERVER_ADDRESS=%%z
if %%x==SERVER_IS_UP (set SERVER_STATE=UP) else (set SERVER_STATE=DOWN)
)
echo %%i [!SERVER_ADDRESS::=!] is !SERVER_STATE! >>%OUTPUT_FILE%
)
The outer loop iterates through the hosts and the inner loop parses the ping output. The first two if statements handle the two possible cases of IP address resolution:
The host name is the host IP address.
The host IP address can be resolved from its name.
If the host IP address cannot be resolved, the address is set to "ADDRESS N/A".
Hope this helps.
Parsing pingtest.txt for each HOST name and result with batch is difficult because the name and result are on different lines.
It is much easier to test the result (the returned error code) of each PING command directly instead of redirecting to a file. It is also more efficient to enclose the entire construct in parens and redirect the final output just once.
>result.txt (
for /f %%i in (testservers.txt) do ping -n 1 %%i >nul && echo %%i UP||echo %%i DOWN
)
I worked on the code given earlier by Eitan-T and reworked to output to CSV file. Found the results in earlier code weren't always giving correct values as well so i've improved it.
testservers.txt
SOMESERVER
DUDSERVER
results.csv
HOSTNAME LONGNAME IPADDRESS STATE
SOMESERVER SOMESERVER.DOMAIN.SUF 10.1.1.1 UP
DUDSERVER UNRESOLVED UNRESOLVED DOWN
pingtest.bat
#echo off
setlocal enabledelayedexpansion
set OUTPUT_FILE=result.csv
>nul copy nul %OUTPUT_FILE%
echo HOSTNAME,LONGNAME,IPADDRESS,STATE >%OUTPUT_FILE%
for /f %%i in (testservers.txt) do (
set SERVER_ADDRESS_I=UNRESOLVED
set SERVER_ADDRESS_L=UNRESOLVED
for /f "tokens=1,2,3" %%x in ('ping -n 1 %%i ^&^& echo SERVER_IS_UP') do (
if %%x==Pinging set SERVER_ADDRESS_L=%%y
if %%x==Pinging set SERVER_ADDRESS_I=%%z
if %%x==SERVER_IS_UP (set SERVER_STATE=UP) else (set SERVER_STATE=DOWN)
)
echo %%i [!SERVER_ADDRESS_L::=!] !SERVER_ADDRESS_I::=! is !SERVER_STATE!
echo %%i,!SERVER_ADDRESS_L::=!,!SERVER_ADDRESS_I::=!,!SERVER_STATE! >>%OUTPUT_FILE%
)
the problem with ping is if the host is not alive often your local machine will return an answer that the pinged host is not available, thus the errorcode of ping will be 0 and your code will run in error because not recognizing the down state.
better do it this way
ping -n 4 %1 | findstr TTL
if %errorlevel%==0 (goto :eof) else (goto :error)
this way you look for a typical string ttl which is always in the well done ping result and check error on this findstr instead of irritating ping
overall this looks like this:
#echo off
SetLocal
set log=path/to/logfile.txt
set check=path/to/checkfile.txt
:start
echo. some echo date >>%log%
:check
for /f %%r in (%check%) do (call :ping %%r)
goto :eof
:ping
ping -n 4 %1 | findstr TTL
if %errorlevel%==0 (goto :eof) else (goto :error)
:error
echo. some errormessage to >>%log%
echo. some blat to mail?
:eof
echo. some good message to >>%log%
Try this
$servers = Get-Content test.txt
$reg=""
foreach ($server in $servers)
{
$reg=$reg+$server+"`t"+([System.Net.Dns]::GetHostAddresses($server) | foreach {echo $_.IPAddressToString})+"`n"
}
$reg >reg.csv
#echo off
set workdir={your working dir. for example - C:\work }
set iplist=%workdir%\IP-list.txt
setlocal enabledelayedexpansion
set OUTPUT_FILE=%workdir%\result.csv
>nul copy nul %OUTPUT_FILE%
echo HOSTNAME,LONGNAME,IPADDRESS,STATE >%OUTPUT_FILE%
for /f %%i in (%iplist%) do (
set SERVER_ADDRESS_I=UNRESOLVED
set SERVER_ADDRESS_L=UNRESOLVED
for /f "tokens=1,2,3" %%x in ('ping -a -n 1 %%i ^&^& echo SERVER_IS_UP') do (
if %%x==Pinging set SERVER_ADDRESS_L=%%y
if %%x==Pinging set SERVER_ADDRESS_I=%%z
if %%x==SERVER_IS_UP (set SERVER_STATE=UP) else (set SERVER_STATE=DOWN)
)
echo %%i [!SERVER_ADDRESS_L::=!] !SERVER_ADDRESS_I::=! is !SERVER_STATE!
echo %%i,!SERVER_ADDRESS_L::=!,!SERVER_ADDRESS_I::=!,!SERVER_STATE! >>%OUTPUT_FILE%
)
This worked great I just add the -a option to ping to resolve the
hostname. Thanks https://stackoverflow.com/users/4447323/wombat
#echo off
setlocal enabledelayedexpansion
set OUTPUT_FILE=result.csv
>nul copy nul %OUTPUT_FILE%
echo HOSTNAME,LONGNAME,IPADDRESS,STATE >%OUTPUT_FILE%
for /f %%i in (testservers.txt) do (
set SERVER_ADDRESS_I=UNRESOLVED
set SERVER_ADDRESS_L=UNRESOLVED
for /f "tokens=1,2,3" %%x in ('ping -n 1 -a %%i ^&^& echo SERVER_IS_UP') do (
if %%x==Pinging set SERVER_ADDRESS_L=%%y
if %%x==Pinging set SERVER_ADDRESS_I=%%z
if %%x==SERVER_IS_UP (set SERVER_STATE=UP) else (set SERVER_STATE=DOWN)
)
echo %%i [!SERVER_ADDRESS_L::=!] !SERVER_ADDRESS_I::=! is !SERVER_STATE!
echo %%i,!SERVER_ADDRESS_L::=!,!SERVER_ADDRESS_I::=!,!SERVER_STATE! >>%OUTPUT_FILE%
)
This works for spanish operation system.
Script accepts two parameters:
a file with the list of IP or domains
output file
script.bat listofurls.txt output.txt
#echo off
setlocal enabledelayedexpansion
set OUTPUT_FILE=%2
>nul copy nul %OUTPUT_FILE%
for /f %%i in (%1) do (
set SERVER_ADDRESS=No se pudo resolver el host
for /f "tokens=1,2,3,4,5" %%v in ('ping -a -n 1 %%i ^&^& echo SERVER_IS_UP')
do (
if %%v==Haciendo set SERVER_ADDRESS=%%z
if %%v==Respuesta set SERVER_ADDRESS=%%x
if %%v==SERVER_IS_UP (set SERVER_STATE=UP) else (set SERVER_STATE=DOWN)
)
echo %%i [!SERVER_ADDRESS::=!] is !SERVER_STATE! >>%OUTPUT_FILE%
echo %%i [!SERVER_ADDRESS::=!] is !SERVER_STATE!
)

Resources