I’m trying to create one of my first ever DOS script (more used to bash).
I’m trying to create a script that would rename my pics using a sequential number and the year as a prefix. I created this script :
@ECHO OFF
setlocal EnableDelayedExpansion
echo.
SET /P Year=Please enter Year (YYYY) :
SET /P Start=Starting Number :
dir
set /A i=%Start%
for %%f in (*.JPG) do call :renameit "%%f"
goto done
:renameit
echo %1 %i%
set str=%i%
set str=0000!str:.=!
set str=!str:~-4!
ren %1 PICT_%Year%_%str%.JPG
set /A i+=1
:done
Issue is that it sometimes works fine, sometimes goes through one additional look renaming back a file that was already renamed. Here are 2 examples (as you can see, I added a DIR and ECHO in the script above for troubleshooting) :
RUN 1 (CORRECT) :
Directory of C:\TEST
07/01/2013 10:55 <DIR> .
07/01/2013 10:55 <DIR> ..
04/08/2011 14:28 16.823 PICT_2012_0005.JPG
04/08/2011 14:28 16.823 PICT_2012_0006.JPG
04/08/2011 14:28 16.823 PICT_2012_0007.JPG
07/01/2013 10:56 368 script.cmd
4 File(s) 50.837 bytes
2 Dir(s) 30.342.901.760 bytes free
"PICT_2012_0005.JPG" 5
"PICT_2012_0006.JPG" 6
"PICT_2012_0007.JPG" 7
RUN 2 (FAILED) :
Directory of C:\TEST
07/01/2013 10:56 <DIR> .
07/01/2013 10:56 <DIR> ..
04/08/2011 14:28 16.823 PICT_2011_0005.JPG
04/08/2011 14:28 16.823 PICT_2011_0006.JPG
04/08/2011 14:28 16.823 PICT_2011_0007.JPG
07/01/2013 10:56 368 script.cmd
4 File(s) 50.837 bytes
2 Dir(s) 30.342.901.760 bytes free
"PICT_2011_0005.JPG" 5
"PICT_2011_0006.JPG" 6
"PICT_2011_0007.JPG" 7
"PICT_2012_0005.JPG" 8
Any idea what I’m doing wrong ?
Thanks
Expanded Comment into a full answer.
It is a known feature/issue/undefined behavior of the
forcommand. When looping through a directory of files and making modification to those files, the for loop does not keep a static list of files in the folder. Instead it just checks for the next file until nothing is returned from the file system. However, when modifying files in the loop, the file system sees the modification as an additional file and it gets sent again to the for loop. This will cause an unknown number (based upon the race condition of the for loop and file system) of files to be reprocessed.See this forum for an in depth discussion about it.
http://www.dostips.com/forum/viewtopic.php?f=3&t=4138&sid=463cb91964f497c478afcca79c33384a
You can alternatively use this for statement:
for /F "delims=" %%F in ('dir /B *.jpg') do call :renameit "%%~fF"The
dircommand will generate a static list of the files in the directory at its run time preventing the recursion of files.