AquaAlex
AquaAlex

Reputation: 380

Issue with Windows Batch Script - replace

Hi have a for loop that I use to get entries out of a lsit of drives to loop through, for each drive I loop through entries in a file, this all works. But then what I am trying to do is finding the entry from the file (which is a file name and path without the drive letter and the first folder (parent folder named %_TAG%)

Ok so far so good, now what I want to do is replace the extension of the file with a r (*.w or *.p or *.cls must become *.r)

But for some reason my command does not work (set str=!str:.w=.r!) I have tried replacing the ! with %

I have tried various things and still stuck. Here is my complete batch file. It reads in a file with a list of partial path and file names. I even tried using a function to do renaming

:bof
    @echo on
    cls
    setlocal enabledelayedexpansion
:init
    set _TAG=TST
    set /p _INFILE="Enter Filename to use for investigation: "
    set _INFILE=%CD%\%_INFILE%
    set /p _TAG="To which environment did you deploy? (TST / LIV): "
    if /i "%_TAG%"=="LIV" (
      set _drive=M O P R S Y X
    ) else (
      set _drive=M T X
    )
:confirm
    echo We will use code in the: %_TAG% folder and file: %_INFILE% and drives: %_drive%
    set /p _continue="Do you wish to continue (Y/N): "
    if /i "%_continue%"=="N" goto :eof
    echo We will use code in the: %_TAG% folder and file: %_INFILE% and drives: %_drive%  1>> %_INFILE%.%_TAG%.rlog 2>&1
:dowork
    for %%j in (%_drive%) do (
        echo ...
        echo investigating: %%j:\%_TAG%\ 1>> %_INFILE%.%_TAG%.rlog 2>&1
        %%j:
        cd %%j:\%_TAG%\
        for /f %%i in (%_INFILE%) DO  ( 
            set "string=%%i"
            call:mySetPathFunc !string! "/"    "\"
            call:mySetPathFunc !string! ".w"   ".r"
            call:mySetPathFunc !string! ".p"   ".r"
            call:mySetPathFunc !string! ".cls" ".r"
            if exist %%j:\%_TAG%\!string! (
                echo I found you in correct folder 1>> %_INFILE%.%_TAG%.rlog 2>&1
            ) else ( 
                echo I did not find you in correct folder 1>> %_INFILE%.%_TAG%.rlog 2>&1
            )
            call:mySetPathFunc !string! "cbsrc"  "tty"
            call:mySetPathFunc !string! "hotfix" "tty"
            if exist %%j:\%_TAG%\%%string%% (
                echo I found you in tty 1>> %_INFILE%.%_TAG%.rlog 2>&1
            ) else ( 
                echo I did not find you in tty 1>> %_INFILE%.%_TAG%.rlog 2>&1
            )

        )
    )
:eof
  ECHO Done used - tag: %_TAG% and used file: %_INFILE% to drive %_drive%
  ECHO Done used - tag: %_TAG% and used file: %_INFILE% to drive %_drive% 1>> %_INFILE%.%_TAG%.rlog 2>&1
  timeout /t 8 /nobreak > NUL
  c:
  exit /b 

::--------------------------------------------------------
::-- Function section starts below here
::--------------------------------------------------------

:mySetPathFunc    - passing a variable by reference
      echo before %~1 1>> %_INFILE%.%_TAG%.rlog 2>&1
    set %~1=%~1:%~2=%~3
      echo after %~1 1>> %_INFILE%.%_TAG%.rlog 2>&1
goto:eof

Upvotes: 0

Views: 40

Answers (1)

Magoo
Magoo

Reputation: 80113

Generation 955 of the "delayedexpansion" problem.

Within a block statement (a parenthesised series of statements), the entire block is parsed and then executed. Any %var% within the block will be replaced by that variable's value at the time the block is parsed - before the block is executed - the same thing applies to a FOR ... DO (block).

Hence, IF (something) else (somethingelse) will be executed using the values of %variables% at the time the IF is encountered.

Two common ways to overcome this are 1) to use setlocal enabledelayedexpansion and use !var! in place of %var% to access the changed value of var or 2) to call a subroutine to perform further processing using the changed values.

Where flags are involved, the situation changes again. set "flag=" will ensure a flag is cleared. set "flag=somethingelse" will ensure it is set (the value is not relevant.) Using if defined flag (doiftrue) else (doiffalse) works on the run-time (current) status of flag - not the parse-time value.

Look for hundreds of items about delayedexpansion on SO for solutions.

Upvotes: 1

Related Questions