Batch File Filter loop output - batch-file

The code runs a very simple process of pinging multiple addresses endlessy and outputting the results to a log file until manually stopped.
#echo off
title ping_logger
set d1=%date:~4%
set d2=%d1:/=-%
set t1=%time::=.%
set t2=%t1: =%
set host=X.X.X.1;X.X.X.162
set hostname=%host:;=+%
set pinghostname=%host:;= and %
set logfile=Log_%hostname%_%ComputerName%_%d2%_%t2%.csv
setlocal enableextensions ENABLEDELAYEDEXPANSION
set counter=0
for %%A IN (%host%) DO (
set /a counter+=1
)
endlocal && set counter=%counter%
echo Target Host(s) = %host%>%logfile%
echo Pinging %pinghostname% with 32 bytes of data: >>%logfile%
timeout %counter% >NUL
:Ping
FOR %%A IN (%host%) DO (
for /F "tokens=* skip=2" %%A in ('ping %%A -n 1 ') do (
echo %date:~4%, %time:~0,2%:%time:~3,2%:%time:~6,2%, %%A>>%logfile%
echo %date% %time:~0,2%:%time:~3,2%:%time:~6,2%, %%A
)
)
IF (%counter% LSS 2) timeout 1 >NUL
GOTO Ping
The output is capturing too much into the log file. I'm looking to only get the first line from each response such as the highlighted lines

:DoPing
FOR %%A IN (%host%) DO (
set "pung="
for /F "tokens=* skip=2" %%A in ('ping %%A -n 1 ') do if not defined pung (
echo %date:~4%, %time:~0,2%:%time:~3,2%:%time:~6,2%, %%A>>%logfile%
echo %date% %time:~0,2%:%time:~3,2%:%time:~6,2%, %%A
set "pung=Y"
)
)
IF (%counter% LSS 2) timeout 1 >NUL
GOTO DoPing
(I'm allergic to using keywords/executable names as labels)
Simply set a flag value pung to nothing so that it is undefined when the pings start. On reporting the first line, set pung to non-empty, so it is then defined and the remining report lines are suppressed.
Next loop of %%A clears pung before issuing the ping for the next host...
Another way:
:DoPing
FOR %%A IN (%host%) DO (
for /F "tokens=1* skip=2" %%A in ('ping %%A -n 1 ') do if "%%A" == "Reply" (
echo %date:~4%, %time:~0,2%:%time:~3,2%:%time:~6,2%, %%A %%B>>%logfile%
echo %date% %time:~0,2%:%time:~3,2%:%time:~6,2%, %%A %%B
)
)
IF (%counter% LSS 2) timeout 1 >NUL
GOTO DoPing
This time, see whether the first token is the string Reply and only write the report if this is so.

Related

Batch script to check the content and file name

I have a code in batch script which will check if the name of the file is same or content of the file is same or not. Also it will updat the ini file to 0 or 1
0 - if the file names are different
1 - if the file names are different
Below is my code
#ECHO OFF
CLS
del /s C:\deep\output.log > NUL
for %%i in (C:\deep\*.DAT) do (
for /f "tokens=1,2 delims= " %%G in (app.ini) do set %%G=%%H
echo Rungmis %rungmis%
fc C:\deep\MAI_ZSYS_MOVE.DAT %%i > NUL
if errorlevel 1 (
CALL :error
echo C:\deep\MAI_ZSYS_MOVE.DAT and %%i are different >>output.log
set /a rungmis=0
echo Rungmis %rungmis%
timeout 5
) ELSE (
CALL :next
echo C:\deep\MAI_ZSYS_MOVE.DAT and %%i are same >>output.log
set /a rungmis=1
echo Rungmis %rungmis%
timeout 5
)
)
for %%I in (rungmis) do (
setlocal enabledelayedexpansion
type app.ini | find /v "%%I=">settings.tmp
move /y settings.tmp gmisapp.ini
echo %%I=!%%I!>>app.ini
)
type app.ini
timeout 5
It is updating the .ini flag (rungmis flag) to 0 or 1. But the problem which i am facing is whenever the ini is getting updated the flag (rungmis) is getting updated at the last line of the ini
Actual app.ini file
[TO_RUN_GMIS]
rungmis=1
;0 means GMIS will run
;1 means GMIS will not run
[Registry_Directories]
ArchivePath=D:\maibackup\
ImportPath=D:\gmisdata\
ExportPath=D:\www\GMIS\excel\
DataSource=GMIS_DEV_NEW
app.ini after getting updated
[TO_RUN_GMIS]
;0 means GMIS will run
;1 means GMIS will not run
[Registry_Directories]
ArchivePath=D:\maibackup\
ImportPath=D:\gmisdata\
ExportPath=D:\www\GMIS\excel\
rungmis=1
can anyone please help me out with that?
Please give this a try.
#ECHO OFF
CLS
del /s C:\deep\output.log > NUL
for %%i in (C:\deep\*.DAT) do (
for /f "tokens=1,2 delims= " %%G in (app.ini) do set %%G=%%H
echo Rungmis %rungmis%
fc C:\deep\MAI_ZSYS_MOVE.DAT %%i > NUL
if errorlevel 1 (
CALL :error
echo C:\deep\MAI_ZSYS_MOVE.DAT and %%i are different >>output.log
set /a rungmis=0
echo Rungmis %rungmis%
timeout 5
) ELSE (
CALL :next
echo C:\deep\MAI_ZSYS_MOVE.DAT and %%i are same >>output.log
set /a rungmis=1
echo Rungmis %rungmis%
timeout 5
)
)
for /f "tokens=*" %%a in ('type "app.ini" ^| find /v /n "" ^& break ^> "app.ini"') do (
set "str=%%a"
setlocal enabledelayedexpansion
set "str=!str:*]=!"
if "!str:~0,7!"=="rungmis" set "str=!str:~0,-1!%rungmis%"
>>app.ini echo(!str!
endlocal
)
type app.ini
timeout 5
So we simply do a type on the file and add some additional characters to ensure we replicate newlines as well. We then get rid of those characters before printing to file. But first we search for the string rungmis and replaces its value with the value you determined earlier in the script. Then each line gets printed back into the app.ini file with the replacement value.

.bat - ping list of IPs and reply with response time only

I'm stuck on this one, I've managed to create a batch file that imports list of IPs & hostnames but when I test for success or failure, I'd like to output how long it took. I don't know how to capture this and include it in the output. I'm trying to hide the default ping.exe output. Here's my code
#echo off
for /F "tokens=1,2 delims= " %%A in (computers.txt) do (
rem ping -n 1 %%A | findstr /i "TTL=" | find "Reply" > nul
if %errorlevel% == 0 (
echo %%B %%A successful ping in ?? Seconds
echo %%B %%A successful ping [%date%, %time%] >> log.txt
)
)
Pause
I've figured it out:
#echo off
setlocal enableDelayedExpansion
for /F "tokens=1,2 delims= " %%A in (computers.txt) do (
for /f "tokens=7 delims== " %%G in ('ping -n 1 %%A') do (
ping -n 1 %%A >nul
if errorlevel 1 (
echo %%B %%A unsuccessful ping
echo %%B %%A unsuccessful ping [!date!, !time!] >> log.txt
) else if "%%~G" NEQ "of" if "%%~G" NEQ "0" (
set ms=%%~G
set ms=!ms:ms=!
for /f %%Z in ('powershell !ms!/1000') do set second=%%~Z
echo %%B %%A successful ping in !second! seconds
echo %%B %%A successful ping [!date!, !time!] >> log.txt
)
)
)
Pause
Using FOR /F, it is possible to process command output.
As you may see, I have 2 ping -n 1 %%A. It is because FOR /F doesn't capture the ERRORLEVEL generated by the processing command. The first command gets the output, the second gets ERRORLEVEL.
if "%%~G" NEQ "of" if "%%~G" NEQ "0" filters out the unneeded results.
The powershell command converts milliseconds to second(batch file does not support decimal numbers)
I/O example
I don't have any other computers on my network, therefore I tested it with URLs.
Input -> Output
www.google.com A A www.google.com successful ping in 0.002 seconds
www.yahoo.com B B www.yahoo.com successful ping in 0.032 seconds
a.a.a C C a.a.a unsuccessful ping

Removing values from set in Batch

I'm trying to write a script for work that tells me which machines on a network are online and which are offline.
Currently I have it showing me online/offline status, taking the PC names from a text file as input into a set variable.
The code I have so far is:
#echo off
setlocal EnableDelayedExpansion
for /F "tokens=*" %%a in (VC.txt) do call :append %%a
:ping
for %%i in (%VC) do (
ping %%1 -n 1 >nul
call :test %%i
)
echo.
goto :ping
:test
IF %ERRORLEVEL% EQU 0 (
echo Pinging %1
) else (
echo Off %1
)
goto :eof
:append
if defined VC (
set VC=%VC% %1
) else (
set VC=%1
)
What I want to happen is once a machine comes online, to remove it from the list. Basically just only show the list of the offline machines.
Is this possible without wiping the whole set and creating it fresh?
This mod do what you want:
:test
IF %ERRORLEVEL% EQU 0 (
echo Pinging %1
REM Remove this machine from the list
set "VC=!VC: %1=!"
) else (
echo Off %1
)
goto :eof
However, you have a couple small errors in your code. This is the fixed section:
:ping
for %%i in (%VC%) do (
ping %%i -n 1 >nul
call :test %%i
)
echo.
goto :ping
A couple points unrelated to your problem. If the machine names are single words with no spaces, then the "tokens=*" part in the for command is not needed. Also, all those call's and subroutines just complicate the code. This is the way I would do this:
#echo off
setlocal EnableDelayedExpansion
set "VC="
for /F %%a in (VC.txt) do set "VC=!VC! %%a"
:ping
for %%i in (%VC%) do (
ping %%i -n 1 >nul
IF !ERRORLEVEL! EQU 0 (
echo Pinging %%i
REM Remove this machine from the list
set "VC=!VC: %%i=!"
) else (
echo Off %%i
)
)
echo/
if defined VC goto :ping
echo All machines are on line

Some portions of code in batch files are not executing

I have a problem in this batch file:
#echo off
setlocal enableextensions EnableDelayedExpansion
for /f "tokens=*" %%l in (input1.txt) do (
ping %%l> "Result.txt"
set "var=HI"
set "var1=hi"
set "var2=1";
FIND /c "Destination host unreachable." Result.txt && ( set "var2=2") || ( echo HI)
FIND /c "Request timed out." Result.txt && ( set "var2=2" ) || (echo HI)
if "!var2!" EQU "2" (echo %%l>>"failure.txt")
# This block doesn't work
if "!var2!" EQU "1" (
for /f "tokens=*" %%i in (Result.txt) do ( set var=%%i)
for /f "tokens=9" %%j in ("%var%") do (set var1=%%j)
set var1="!var1:~0,-2!"
if "!var1!" LSS "1000" (echo %%l >> "success.txt") ELSE (echo %%l >>"timeout.txt")
)
)
endlocal
The above code is designed for ping bulk list of servers and redirect the servers to successful or failure text files based on the test results. Here the problem is the code marked by a rem remark is not working. It seems that portion is not executed. Also var1 is not being evaluated. Thanks in advance.
This will give you success or failure.
#echo off
for /f "delims=" %%a in (input1.txt) do (
ping %%l >nul
if errorlevel 1 (
>>"failure.txt" echo %%l
) else (
>>"success.txt" echo %%l
)
)
A problem in your code is that you are forcing string compares by using quotes around "!var1!" and the numeral.
You also have two sets of quotes around !var1!

Batch file help - adding output from command to csv file

I currently have a batch file that reads a list of computer names and pings each of these and outputs the ones that reply to a csv file with the computer name and ip address.
I now need to edit this to also find out the user of the machine. I need to contact users which are online to arrange some work done to their computer. Their can be over a hundred machines in the batch file so to manually find out each user takes time. Is there a way to do this?
`IF EXIST C:\test\new.csv (del C:\test\new.csv)
IF EXIST C:\test\final.csv (del C:\test\final.csv)
set ComputerList=C:\test\ClientList.txt
Echo Computer Name,IP Address>Final.csv
setlocal enabledelayedexpansion
echo please wait...
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!>>final.csv
)
)
findstr /V "IPAddress" final.csv >> C:\test\new.csv
echo identified machines for Install
start excel C:\test\new.csv
echo opened csv file`
The command I want to use to get the username is:
`wmic.exe /NODE: %%A COMPUTERSYSTEM GET USERNAME`
Thanks
Mark
Here is a function I wrote to do just what you are trying to do:
:GetLoggedInUser comp user
for /f %%u in (
'wmic /NODE:"%1" Computersystem get username^|find "\"') do (
if not errorlevel 1 ( for /f "tokens=2 delims=\" %%a in (
'wmic /NODE:"%1" Computersystem get username^|find "\"' ) do (
For /f %%b in ("%%a") do (set %2=%%b))
) ELSE (for /f "skip=1" %%a in (
'wmic /NODE:"%1" Computersystem get username' ) do (
For /f %%b in ("%%a") do (set %2=%%b))
))
Exit /b
Here is my function for pinging. It returns a 0 if the ping succeeded and a 1 otherwise.
:IsPingable comp
ping -n 1 -w 3000 -4 -l 8 "%~1" | Find "TTL=">nul
exit /b
Usage example:
for /l %%a in (1,1,255) do (
call:IsPingable 10.6.1.%%a && (
echo ping 10.6.1.%%a used )||( echo ping 10.6.1.%%a unused )
)
And here is for if you're pinging IP's and want to return the hostname as well:
:IsPingable2 comp ret
setlocal
for /f "tokens=2" %%a in (
'"ping -a -n 1 -4 "%~1" | Find "Pinging" 2>nul"') do set name=%%a
endlocal & set %~2=%name%
ping -n 1 -w 3000 -4 -l 8 "%~1" | Find "TTL=">nul
exit /b
Usage example:
#echo off
setlocal enabledelayedexpansion
for /l %%a in (1,1,255) do (
call:IsPingable2 10.6.1.%%a host && (
echo ping !host! - 10.6.1.%%a used )||( echo ping !host! - 10.6.1.%%a unused )
)
I just posted these because they just might come in handy for this type of thing in the future. You can use the :IsPingable now though.
You would use it like this in your code:
IF EXIST C:\test\final.csv (del C:\test\final.csv)
set ComputerList=C:\test\ClientList.txt
Echo Computer Name,IP Address,Logged In User>Final.csv
setlocal enabledelayedexpansion
echo please wait...
echo.
for /f "usebackq tokens=*" %%A in ("%ComputerList%") do (
for /f "tokens=3" %%B in ('ping -n 1 -l 1 %%A ^|find "TTL="') do (
if not errorlevel 1 (
set IPadd=%%B
call :GetLoggedInUser %%B uname
echo %%A,!IPadd:~0,-1!,!uname!>>final.csv
)
)
)
echo identified machines for Install
start excel C:\test\final.csv
echo opened csv file
goto :eof
:GetLoggedInUser comp user
for /f %%u in (
'wmic /NODE:"%1" Computersystem get username^|find "\"') do (
if not errorlevel 1 ( for /f "tokens=2 delims=\" %%a in (
'wmic /NODE:"%1" Computersystem get username^|find "\"' ) do (
For /f %%b in ("%%a") do (set %2=%%b))
) ELSE (for /f "skip=1" %%a in (
'wmic /NODE:"%1" Computersystem get username' ) do (
For /f %%b in ("%%a") do (set %2=%%b))
))
Exit /b
The below code will count the number of lines in two files sequentially and is set to the variables SalaryCount and TaxCount.
#ECHO OFF
echo Process started, please wait...
for /f %%C in ('Find /V /C "" ^< "D:\Trial\Salary.txt"') do set SalaryCount=%%C
echo Salary,%SalaryCount%
for /f %%C in ('Find /V /C "" ^< "D:\Trial\Tax.txt"') do set TaxCount=%%C
echo Tax,%TaxCount%
Now if you need to output these values to a csv file, you could use the below code.
#ECHO OFF
cd "D:\CSVOutputPath\"
echo Process started, please wait...
echo FILENAME,FILECOUNT> SUMMARY.csv
for /f %%C in ('Find /V /C "" ^< "D:\Trial\Salary.txt"') do set Count=%%C
echo Salary,%Count%>> SUMMARY.csv
for /f %%C in ('Find /V /C "" ^< "D:\Trial\Tax.txt"') do set Count=%%C
echo Tax,%Count%>> SUMMARY.csv
The > will overwrite the existing content of the file and the >> will append the new data to existing data. The CSV will be generated in D:\CSVOutputPath

Resources