batch file with echo findstr not working inside for loop - batch-file

I have multiple string that come from a reg query inside a for loop.
I want to validate for each of them if it has certain words and do actions if it has.
My code is this:
for /l %%g in (0 1 3) do (
echo HOME%%g
for /f "tokens=1,2,3*" %%h in ('reg query \\%%c\HKLM\SOFTWARE\ORACLE\HOME%%g /v ORACLE_HOME') do (
echo HOME%%g
echo %%j
echo %%j | findstr /I /R /C:"806"
if %ERRORLEVEL% equ 0 (
echo YES
) else (
echo NO
)
echo %%j | findstr /C:".isuites."
if %ERRORLEVEL% equ 0 (
echo YES
) else (
echo NO
)
echo %%j | findstr /I ora90
if errorlevel 0 (
echo YES
) else (
echo NO
)
echo %%j | findstr /I forms10
if errorlevel 0 (
echo YES
) else (
echo NO
)
)
)
The problem is that is does not validates the string as seen in the output
HOME0
HOME0
ECHO is off.
YES
YES
YES
YES
HOME0
d:\oracle\806
d:\oracle\806
YES
YES
YES
YES
HOME1
HOME1
ECHO is off.
YES
YES
YES
YES
HOME1
d:\oracle\iSuites
YES
YES
YES
YES
HOME2
HOME2
ECHO is off.
YES
YES
YES
YES
HOME2
d:\oracle\ora90
YES
YES
d:\oracle\ora90
YES
YES
HOME3
HOME3
ECHO is off.
YES
YES
YES
YES
HOME3
D:\oracle\forms10g
YES
YES
YES
D:\oracle\forms10g
YES

Some corrections are needed in your code
Change for %%h into
for /f "tokens=1,2,*" %%h in ('reg query \\%%c\HKLM\SOFTWARE\ORACLE\HOME%%g /v ORACLE_HOME ^| find "REG_SZ" ') do (
That way, the ORACLE_HOME key name will be in %%h, the REG_SZ type in %%i and the folder in %%j (i supose this is what you intended)
With this done, the next problem is errorlevel checks
When a block of code (code inside parenthesis) is parsed, all variable reads are replaced with the value inside the variable before starting to execute the block. So, if you use %errorlevel% inside you block of code, as this variable read has been replaced with the value of the variable before starting to execute, you will not see the real value.
You can use delayed expansion (include setlocal enabledelayedexpansion at the start of batch file) and change the syntax from %errorlevel% to !errorlevel! to indicate to the parser that the variable read should be delayed until the moment the command is executed.
Or you can use the if errorlevel n ... syntax. In this case you should remember that the condition will be true for any errorlevel value greater or equal than the indicated value.
That is, if errorlevel is 1, both if errorlevel 1 and if errorlevel 0 will be true. For this reason, the proper way of checking error level is to check from greater values to lower values
echo %%j | findstr .....
if errorlevel 1 (
...
) else (
...
)
So, your code should be something like
....
....
for /l %%g in (0 1 3) do (
echo Testing HOME%%g
echo ---------------------------------
for /f "tokens=1,2,*" %%h in (
'reg query \\%%c\HKLM\SOFTWARE\ORACLE\HOME%%g /v ORACLE_HOME 2^>nul ^| find "REG_SZ" '
) do (
echo %%j | findstr /L /C:"806"
if errorlevel 1 (
echo NO
) else (
echo YES
)
echo %%j | findstr /C:".isuites."
if errorlevel 1 (
echo NO
) else (
echo YES
)
echo %%j | findstr /I /C:"ora90"
if errorlevel 1 (
echo NO
) else (
echo YES
)
echo %%j | findstr /I /C:"forms10"
if errorlevel 1 (
echo NO
) else (
echo YES
)
)
)
)
edited to adapt to comments
Some of the HOMEn will not be echoed if they does not exist in registry. To "solve" it, the error output from req query is included in the data to be parsed and it is tested if the string ERROR: is found.
for /l %%g in (0 1 3) do (
echo Testing HOME%%g
echo ---------------------------------
for /f "tokens=1,2,*" %%h in (
'reg query \\%%c\HKLM\SOFTWARE\ORACLE\HOME%%g /v ORACLE_HOME 2^>^&1 ^| findstr /L /C:"REG_SZ" /C:"REG_EXPAND_SZ" /C:"ERROR:" '
) do (
for %%z in ("806" ".isuites." "ora90" "forms10") do (
(if "%%h"=="ERROR:" (echo() else (echo %%j)) | findstr /i /c:"%%~z"
if errorlevel 1 (
echo NO
) else (
echo YES
)
)
)
)
)

Related

how to check if a variable is not null and print it - batch file

sometimes the ping fails and returns " " , i need to skip that empty line and if it's not empty print it
and count how many pings were successful
#echo off
for /l %%h in (1,1,10) do (
for /f "tokens=*" %%g in (' "ping -n 1 1.1.1.%%h | find /i "ttl" "') do (
if %%g ** *ITSNOTNULL *** (
set/a counter+=1
msg * %%g
)
)
)
pause>nul
exit
Something like this?
#echo off
SetLocal EnableDelayedExpansion
set counter=0
for /l %%h in (1,1,10) do (
for /f "tokens=*" %%g in (' "ping -n 1 1.1.1.%%h | find /i "ttl" "') do (
if not "%%g"=="" (
set /a counter=!counter!+1
echo * %%g )
)
)
echo %~NX0 complete.
echo Total IP addresses: %counter%
EndLocal
pause>nul
Instead of if %%g ** *ITSNOTNULL *** I used if not "%%g"==""
To use a variable within a for loop, if you want to maintain its state, you have to use "DelayedExpansion". This changes the syntax from %thingy% to !thingy!. The reasons for this can be found here
You also can use | findstr . with operator && and || to check any character in variable:
echo/ %%G or %Any_Variable% | findstr . >nul && (echo/Found something) || (echo/Nothing Found!!)
#echo off && SetLocal EnableDelayedExpansion
for /L %%L in (1 1 10)do for /f tokens^=* %%G in ('ping -n 1 1.1.1.%%L^|find "TTL"
')do echo/%%~G|findstr .>nul && (echo/ * %%G && set /a "_cnt+=1+0" ) || goto :next
:next
echo/ - %~NX0 complete^^! && echo/ - Total IP addresses: 0!_cnt! & timeout -1 >nul
endlocal & goto :EOF

Breaking out of for loop in batch file when using goto

I need to run a program for each line in a file. I am triggering four instances at a time. After four instances, waiting for some time and triggering another one. After wait time batch script is breaking.
Please suggest if I'm doing wrong.
for /F "tokens=*" %%J in ( %JobListFile% ) do (
SET JobName=%%J
echo job name !JobName!
if "!JobName!" equ "" (
echo joblist not found... rerun the script..
REM exit /b
) else (
:waittofinish
for /F "tokens=*" %%a in ( 'tasklist /fi "IMAGENAME eq dsexport.exe" ^| grep -c "dsexport.exe"' ) do ( SET /A CurrInstances=%%a )
echo current instance is !CurrInstances!
echo parallelism set to !NoOfParallelInstances!
if "!CurrInstances!" gtr "!NoOfParallelInstances!" (
echo going to wait
sleep 5
goto waittofinish
echo failed to go wait label...
) else (
echo Exporting job: !JobName! ...............Starting
start /b cmd /C "C:/IBM/9.1/InformationServer/Clients/Classic/dsexport.exe /D=%vDomain% /U=%vuserID% /P=%vpassword% /H=%vServer% %vDSProject% /NODEPENDENTS /JOB=!JobName! %tmppath%\!JobName!.dsx"
echo.
echo.
)
)
)
echo script completed...
exit /b
goto :Label breaks the block context of a code block in parentheses ( ... ); this is also true for for ... do ( ... ) loops and if ... ( ... ) else ( ... ) conditions.
To overcome this, you can put the code portion with goto and :Label into a subroutine, because this hides the block context of the calling code portion from goto, like this:
for /F "usebackq tokens=*" %%J in ( "%JobListFile%" ) do (
SET "JobName=%%J"
echo job name !JobName!
if "!JobName!" equ "" (
echo joblist not found... rerun the script..
REM exit /b
) else (
rem /* The `goto` and `:Label` code fragment has been transferred to a subroutine,
rem which receives the current value of variable `JobName` as an argument: */
call :waittofinish "!JobName!"
)
)
echo script completed...
exit /b
:waittofinish JobName
rem // This subroutine contains the `goto` and `:Label` code fragment so that it does no longer appear inside of a block `( ... )`:
for /F "tokens=*" %%a in ( 'tasklist /fi "IMAGENAME eq dsexport.exe" ^| grep -c "dsexport.exe"' ) do ( SET /A CurrInstances=%%a )
echo current instance is !CurrInstances!
echo parallelism set to !NoOfParallelInstances!
if "!CurrInstances!" gtr "!NoOfParallelInstances!" (
echo going to wait
sleep 5
goto :waittofinish
echo failed to go wait label...
) else (
echo Exporting job: %~1 ...............Starting
rem // Not sure if some arguments should be enclosed in `""` in the next line (but I do not know `dsexport.exe`):
start "" /b cmd /C "C:/IBM/9.1/InformationServer/Clients/Classic/dsexport.exe /D=%vDomain% /U=%vuserID% /P=%vpassword% /H=%vServer% %vDSProject% /NODEPENDENTS /JOB=%~1 %tmppath%\%~1.dsx"
echo.
echo.
)
exit /b
N. B.: I didn't check the logic of your script, because I don't have/know grep.exe or dsexport.exe.

Searching for files but may need to time out

I have a program to search drives for a specific file. The only problem is is that i wont know what drive it is on. The problem occurs when it searches a drive for a file that isn't there is there a way to go on to the next drive after say like 10 seconds. Heres my code so far
#echo off
setlocal EnableDelayedExpansion
set count=1
for /f "skip=1" %%a in ('wmic logicaldisk get caption') do (
set drive!count!=%%a
set /a count+=1
)
set "gh=!drive1!"
::Change this to do whatever with the variables
set "fh=!drive2!"
set "hh=!drive3!"
set "jh=!drive4!"
For /R %gh%\ %%G IN (*.ut2) do set jk="%%~dpG"
if defined jk (
echo %jk%
) else (
goto next
)
for /r %jk% %%a in (*) do if "%%~nxa"=="CTF-Hydro-16-2k3.ut2" set k=%%~dpnxa
if defined k (
echo %k% found
pause
cls
echo You have it
goto end
) else (
echo Map not found
copy %CD:~0,3%\Unrealmap\CTF-Hydro-16-2k3.ut2 %jk%
goto end
)
:next
For /R %fh%\ %%G IN (*.ut2) do set ht="%%~dpG"
if defined ht (
echo %ht%
) else (
goto there
)
for /r %ht% %%a in (*) do if "%%~nxa"=="CTF-Hydro-16-2k3.ut2" set m=%%~dpnxa
if defined k (
echo %m% found
pause
cls
echo You have it
goto end
) else (
echo Map not found
copy %CD:~0,3%\Unrealmap\CTF-Hydro-16-2k3.ut2 %jk%
goto end
:there
:end
cls
echo done
pause
#echo off
for /f "skip=1" %%D in ('wmic logicaldisk get caption') do (
for /r "%%D\\" %%G IN (*.ut2) do (
echo %%~dpG
if exist "%%~dpGCTF-Hydro-16-2k3.ut2" (
echo Found the map.
goto end
) else (
echo Map not found, copying
copy %CD:~0,3%\Unrealmap\CTF-Hydro-16-2k3.ut2 "%%~dpG"
goto end
)
)
)
:end
pause
Try next approach:
#ECHO OFF >NUL
SETLOCAL enableextensions
set /A "ii=0"
for /f "skip=1" %%D in ('
wmic logicaldisk get caption
') do for /F %%d in ("%%D") do (
echo searching %%d
for /F "delims=" %%G IN ('dir /B /S "%%d\CTF-Hydro-16-2k3.ut2" 2^>nul') do (
set /A "ii+=1"
set "k=%%G"
rem remove 'rem' from next line to discontinue searching
rem goto :testfound
)
TIMEOUT /T 10 /NOBREAK >NUL
)
:testfound
if %ii% EQU 0 (
echo Map not found
) else (
echo Map found %ii% times: last one "%k%"
)
Here the for loops against wmic command are
%%D to retrieve the caption value;
%%d to remove the ending carriage return in the value returned: wmic behaviour: each output line ends with 0x0D0D0A (<CR><CR><LF>) instead of common 0x0D0A (<CR><LF>).
See Dave Benham's WMIC and FOR /F: A fix for the trailing <CR> problem
Another eventuality: parse
wmic datafile where "Extension='ut2' and FileName='CTF-Hydro-16-2k3'" get Name 2>NUL

Set command output as variable

I have Batch code like this
#echo off
:begin
SET d=netstat -an | find /c "0.0.0.0:80"
rem echo %d%
if %%d == "2" (
echo true
pause
rem exit
) else (
echo false
pause
rem GOTO begin
)
I want make netstat stetment output stored in variable d, and d became parameter from If cluse, What wrong with my file ?
You don't need to set a variable in your case.
This should work :
netstat -an | find /c "0.0.0.0:80" && echo true || echo False
But if you need to have this value in a variable you can do like this :
#echo off
for /f %%a in ('netstat -an ^| find /c "0.0.0.0:80"') do set D=%%a
if %D% equ 2 (
echo true
) else (
echo false)

Editing an external batch config value with batch

I have a config file named config.conf with the content of:
[Config]
password=1234
usertries=0
allowterminate=0
I want to just edit the usertries value to 5, are there any batch script code that can help me do that
Thanks
This gets a little messy, but should work:
#echo off
set ConfigFile=config.conf
setlocal enabledelayedexpansion
(for /f "delims=" %%L in (%ConfigFile%) do (
set "LINE=%%L"
if "!LINE:~0,10!"=="usertries=" (echo usertries=5) else (echo !LINE!)
)) > %ConfigFile%.new
move /y %ConfigFile%.new %ConfigFile% > nul
Basically we're writing each line to a new file, unless it starts with usertries=. In which case we just insert our replacement line. Afterwards we move the new file on top of the old one to replace it.
#ECHO OFF
setlocal
::
:: set %1 to value %2 in config.conf
::
SET target=%2&IF NOT DEFINED target ECHO syntax is %0 keyname newvalue&GOTO :EOF
SET target=Config.conf
MOVE /y %target% %target%.old >NUL
FOR /f "tokens=1*delims==" %%i IN (%target%.old) DO (
IF /i %%i==%1 (ECHO %%i=%2) ELSE (
IF "%%j"=="" (ECHO %%i) ELSE (ECHO %%i=%%j)
)
) >>%target%
With this version, you can change an existing key to a value using
thisbatchname existingkey newvalue
I know I'm a little late to the party, but I decided to write a general purpose ini file utility batch script to address this question.
The script will let you retrieve or modify values in an ini-style file. Its searches are case-insensitive, and it preserves blank lines in the ini file. In essence, it allows you to interact with an ini file as a sort of very rudimentary database.
:: --------------------
:: ini.bat
:: ini.bat /? for usage
:: --------------------
#echo off
setlocal enabledelayedexpansion
goto begin
:usage
echo Usage: %~nx0 /i item [/v value] [/s section] inifile
echo;
echo Take the following ini file for example:
echo;
echo [Config]
echo password=1234
echo usertries=0
echo allowterminate=0
echo;
echo To read the "password" value:
echo %~nx0 /s Config /i password inifile
echo;
echo To change the "usertries" value to 5:
echo %~nx0 /s Config /i usertries /v 5 inifile
echo;
echo In the above examples, "/s Config" is optional, but will allow the selection of
echo a specific item where the ini file contains similar items in multiple sections.
goto :EOF
:begin
if "%~1"=="" goto usage
for %%I in (item value section found) do set %%I=
for %%I in (%*) do (
if defined next (
if !next!==/i set item=%%I
if !next!==/v set value=%%I
if !next!==/s set section=%%I
set next=
) else (
for %%x in (/i /v /s) do if "%%~I"=="%%x" set "next=%%~I"
if not defined next (
set "arg=%%~I"
if "!arg:~0,1!"=="/" (
1>&2 echo Error: Unrecognized option "%%~I"
1>&2 echo;
1>&2 call :usage
exit /b 1
) else set "inifile=%%~I"
)
)
)
for %%I in (item inifile) do if not defined %%I goto usage
if not exist "%inifile%" (
1>&2 echo Error: %inifile% not found.
exit /b 1
)
if not defined section (
if not defined value (
for /f "usebackq tokens=2 delims==" %%I in (`findstr /i "^%item%\=" "%inifile%"`) do (
echo(%%I
)
) else (
for /f "usebackq delims=" %%I in (`findstr /n "^" "%inifile%"`) do (
set "line=%%I" && set "line=!line:*:=!"
echo(!line! | findstr /i "^%item%\=" >NUL && (
1>>"%inifile%.1" echo(%item%=%value%
echo(%value%
) || 1>>"%inifile%.1" echo(!line!
)
)
) else (
for /f "usebackq delims=" %%I in (`findstr /n "^" "%inifile%"`) do (
set "line=%%I" && set "line=!line:*:=!"
if defined found (
if defined value (
echo(!line! | findstr /i "^%item%\=" >NUL && (
1>>"%inifile%.1" echo(%item%=%value%
echo(%value%
set found=
) || 1>>"%inifile%.1" echo(!line!
) else echo(!line! | findstr /i "^%item%\=" >NUL && (
for /f "tokens=2 delims==" %%x in ("!line!") do (
echo(%%x
exit /b 0
)
)
) else (
if defined value (1>>"%inifile%.1" echo(!line!)
echo(!line! | find /i "[%section%]" >NUL && set found=1
)
)
)
if exist "%inifile%.1" move /y "%inifile%.1" "%inifile%">NUL
Example:
C:\Users\me\Desktop>type config.conf
[Config]
password=1234
usertries=0
allowterminate=0
[Other]
password=foo
C:\Users\me\Desktop>ini /i usertries /v 5 config.conf
5
C:\Users\me\Desktop>ini /i usertries config.conf
5
C:\Users\me\Desktop>ini /s config /i password /v bar config.conf
bar
C:\Users\me\Desktop>ini /s other /i password /v baz config.conf
baz
C:\Users\me\Desktop>type config.conf
[Config]
password=bar
usertries=5
allowterminate=0
[Other]
password=baz

Resources