Search code examples
batch-filefor-loopechofindstr

batch file with echo findstr not working inside for loop


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

Solution

  • 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
                    )
                )
            )
        )
    )