Reputation: 3
I'm doing a job, copying files from one location to another location using BATCH file. I split my statements into three parts, one program driver, one for generating file list under each sub-directory, and one for checking file name & doing actual copy stuff.
1.PROGRAM DRIVER
IF EXIST TEMP.TXT DEL TEMP.TXT
CD>TEMP.TXT
set /p ROOT=<TEMP.TXT
rem PARA is the date to copy
SET PARA=2013-08-06
ECHO %PARA%
CD %ROOT%\%PARA%
FOR /R %%A IN (.) DO ( ::COPY SUB-LOGIC FILE TO EACH SUB-DIRECTORY
ECHO NOW IN %%A
CD %%A
XCOPY "%ROOT%\WORK.BAT" . /K /Y
XCOPY "%ROOT%\CORE.BAT" . /K /Y
ECHO LOOP OUT.
)
CD %ROOT%\%PARA%
FOR /R %%A IN (.) DO (
ECHO NOW IN %%A
CD %%A
CALL WORK.BAT ::GENERATING FILE LIST
ECHO LOOP OUT.
)
CD %ROOT%\%PARA%
FOR /R %%A IN (.) DO (
ECHO NOW IN %%A
CD %%A
CALL CORE.BAT ::DOING COPY STUFF
ECHO LOOP OUT.
)
PAUSE
2.WORK.BAT
IF EXIST FILE.TXT DEL FILE.TXT
FOR %%B IN (*.wav) DO ECHO %%~nxB>>FILE.TXT
3.COPYING STUFF
FOR %%F IN ("%CD%") DO SET CURDIR=%%~nxF
IF NOT EXIST FILE.TXT GOTO END
SET CCC="FALSE" ::IF NO CCC DECLARED HERE,BELOW FOR LOOP WILL BE SKIPPED
PAUSE
FOR /F %%C IN (FILE.TXT) DO (
SETLOCAL
SET RES="FALSE"
IF "%%C" GEQ "CH201_00000000_000.WAV" SET RES="TRUE"
IF "%%C" LEQ "CH300_FFFFFFFF_FFF.WAV" (
SET RES="TRUE"
) ELSE ( SET RES="FALSE")
ENDLOCAL& SET CCC=%RES% *::VAR CCC NOT UPDATED*
PAUSE
IF %CCC% EQU "TRUE" (
IF NOT EXIST D:\PHILIPS\%PARA%\%PARA%\%CURDIR% MD D:\PHILIPS\%PARA%\%PARA%\%CURDIR%
XCOPY "%ROOT%\%PARA%\%CURDIR%\%%C" D:\PHILIPS\%PARA%\%PARA%\%CURDIR% /K /Y
)
)
:END
ECHO LOOP OUT
My question is, why my "ENDLOCAL & SET" statement not working, i.e., NULL each time, as pictures show. How can I change my statements to make it work as expected?
I changed part 3 to
FOR %%F IN ("%CD%") DO SET CURDIR=%%~nxF
IF NOT EXIST FILE.TXT GOTO END
SET "RES="
PAUSE
FOR /F %%C IN (FILE.TXT) DO (
SET "RES="
IF "%%C" GEQ "CH201_00000000_000.WAV" SET "RES=Y"
IF "%%C" LEQ "CH300_FFFFFFFF_FFF.WAV" (
SET "RES=Y"
) ELSE ( SET "RES=" )
PAUSE
IF DEFINED RES (
IF NOT EXIST D:\PHILIPS\%PARA%\%PARA%\%CURDIR% MD D:\PHILIPS\%PARA%\%PARA%\%CURDIR%
XCOPY "%ROOT%\%PARA%\%CURDIR%\%%C" D:\PHILIPS\%PARA%\%PARA%\%CURDIR% /K /Y
)
)
It seems that RES always defined, even FILENAME is in specified ranges. In this case, it copied wrong files.
Upvotes: 0
Views: 336
Reputation: 79983
in (3)
FOR /F %%C IN (FILE.TXT) DO (
SETLOCAL
SET RES="FALSE"
IF "%%C" GEQ "CH201_00000000_000.WAV" SET RES="TRUE"
IF "%%C" LEQ "CH300_FFFFFFFF_FFF.WAV" (
SET RES="TRUE"
) ELSE ( SET RES="FALSE")
ENDLOCAL& SET CCC=%RES% *::VAR CCC NOT UPDATED*
PAUSE
IF %CCC% EQU "TRUE" (
IF NOT EXIST D:\PHILIPS\%PARA%\%PARA%\%CURDIR% MD D:\PHILIPS\%PARA%\%PARA%\%CURDIR%
XCOPY "%ROOT%\%PARA%\%CURDIR%\%%C" D:\PHILIPS\%PARA%\%PARA%\%CURDIR% /K /Y
)
)
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.
Note therefore the use of CALL ECHO %%var%%
which displays the changed value of var
. CALL ECHO %%errorlevel%%
displays, but sadly then RESETS errorlevel.
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.
Hence, I suggest you change your processing, setting ccc
to either nothing with a set "ccc="
statement or something with a set "ccc=y"
and you can then test for true/false using if [not] defined ccc
The syntax SET "var=value"
(where value may be empty) is used to ensure that any stray trailing spaces are NOT included in the value assigned. set /a
can safely be used "quoteless".
(on revised code)
Your tests are incorrect.
res
will not be set to Y
with value CH145...
against CH201...
But it will be set to Y
in the LEQ
test as CH145...
is lestt than or equal to CH300...
You may either cascade the setting:
if "%%C" GEQ "CH201..." IF "%%C" LEQ "CH300..." set "res=Y"
or gate the test
IF "%%C" GEQ "CH201_00000000_000.WAV" SET "RES=Y"
if defined res IF "%%C" GTR "CH300_FFFFFFFF_FFF.WAV" SET "RES="
Upvotes: 1