Reputation: 101
I am trying to write a batch file to be run in a command prompt on XP. I am trying to get a listing of files in a specific path that follow a certain naming convention. I need to copy and rename each file instance to a static name and drop it to a transmission folder.
Since it may take a little while for the file to go in the transmission folder, I need to check before I copy the next file over so that I don't overlay the previous file. I am not able to use SLEEP
or TIMEOUT
since I don't have the extra toolkit installed. I try to just continually loop back to a START
section until the file is sent.
I noticed that if I passed the %%x
value set in the for
loop that if I loop back to the START
section a couple of times, it seems to lose its value and it is set to nothing. So I tried to set a variable to hold the value.
I seem to be having issues with the variable not being set correctly or not cleared. Originally it kept on referencing the first file but now it doesn't seem to be set at all. The ECHO
displays the correct the value but the filename
variable is empty still.
Does anyone know a better way of doing this? Thanks in advance for your help as I have already wasted a whole day on this!
This is the batch file:
@ECHO "At the start of the loop"
@for %%x in (C:\OUTBOUND\customer_file*) do (
@ECHO "In the loop"
@ECHO "loop value ="
@ECHO %%x
SET filename=%%x
@ECHO "filename ="
@ECHO %filename%
@ECHO ...ARCHIVE OUTBOUND CUSTOMER FILE
archivedatafile --sourcefile="%filename%" --archivefolder="..\archivedata\customer" --retentiondays=0
IF NOT %ERRORLEVEL%==0 GOTO ERROR
PAUSE
:START
IF EXIST l:\OutputFile (
@ping 1.1.1.1 -n 1 -w 30000
GOTO START
) ELSE (
COPY %filename% l:\OutputFile /Y
IF NOT %ERRORLEVEL%==0 GOTO ERROR
PAUSE
)
)
GOTO END
:ERROR
@echo off
@ECHO *************************************************************
@ECHO * !!ERROR!! *
@ECHO *************************************************************
:END
SET filename=
Upvotes: 2
Views: 2756
Reputation: 130879
foxidrive has provided a script that should work, but did not provide an explanation as to why your code fails and how he fixed the problems.
You have 2 problems:
1) Your FOR loop is aborted immediately whenever GOTO is executed within you loop. It does not matter where the GOTO target label is placed - GOTO always terminates a loop. Foxidrive's use of CALL works perfectly - the loop will continue once the CALLed routine returns.
2) You attempt to set a variable within a block of code and then reference the new value within the same block. %VAR%
is expanded when the statement is parsed, and complicated commands like IF and FOR are parsed once in their entirety in one pass. Actually, any block of code within parentheses is parsed in one pass. So the values of %ERRORLEVEL%
and %FILENAME%
will be constant - the values that existed before the block was entered.
As Endoro has indicated, one way to solve that problem is to use delayed expansion. Delayed expansion must be enabled by using setlocal enableDelayedExpansion
, and then expand the variable using !VAR!
. The value is expanded at execution time instead of parse time. Type HELP SET
from the command prompt for more information about delayed expansion.
But beware that delayed expansion can cause its own problems when used with a FOR loop because the delayed expansion occurs after the FOR variable expansion: %%x
will be corrupted if the value contains a !
. This problem can be solved by carefully toggling delayed expansion ON and OFF as needed via SETLOCAL and ENDLOCAL.
Foxidrive's code avoids the entire delayed expansion issue by using CALL. His :NEXT routine is not inside a FOR loop, so all the commands are reparsed each time it is called, so delayed expansion is not required.
Upvotes: 4
Reputation: 41244
This may work - it is untested:
@echo off
ECHO Starting...
for %%x in (C:\OUTBOUND\customer_file*) do call :next "%%x"
echo done
pause
goto :eof
:next
ECHO ...ARCHIVING OUTBOUND CUSTOMER FILE "%~1"
archivedatafile --sourcefile="%~1" --archivefolder="..\archivedata\customer" --retentiondays=0
IF ERRORLEVEL 1 GOTO :ERROR
:loop
echo waiting for file...
ping -n 6 localhost >nul
IF EXIST l:\OutputFile GOTO :loop
COPY "%~1" l:\OutputFile /Y
IF ERRORLEVEL 1 GOTO :ERROR
GOTO :EOF
:ERROR
ECHO *************************************************************
ECHO * !!ERROR!! in "%%x"
ECHO *************************************************************
pause
goto :EOF
Upvotes: 1
Reputation: 37579
try this:
@echo off&setlocal
for %%x in (C:\OUTBOUND\customer_file*) do SET "filename=%%x"
ECHO %filename%
ECHO ...ARCHIVE OUTBOUND CUSTOMER FILE
archivedatafile --sourcefile="%filename%" --archivefolder="..\archivedata\customer" --retentiondays=0
IF NOT %ERRORLEVEL%==0 GOTO:ERROR
PAUSE
:START
IF EXIST l:\OutputFile ping 1.1.1.1 -n 1 -w 30000&GOTO:START
COPY "%filename%" l:\OutputFile /Y
IF NOT %ERRORLEVEL%==0 GOTO:ERROR
PAUSE
GOTO:END
:ERROR
echo off
ECHO *************************************************************
ECHO * !!ERROR!! *
ECHO *************************************************************
:END
SET "filename="
If you use codeblocks (if
and for
with ( )
) and variables with changing values you have to enable delayed expansion
. You don't need code blocks in this code, as you can see.
Upvotes: 0