2

So I'm trying to write a batch that renames <randomname>.EPL to fbXYZ.EPL (XYZ - number with leading zeroes)

So something like bes_rush.EPL should turn into fb001.EPL and other files should get renamed too (fb002.EPL, fb003.EPL, etc.)

Here's what I have so far

setlocal ENABLEDELAYEDEXPANSION
set/a fileNum = 0
set fileNum=0000%fileNum%
set fileNum=%fileNum:~-3%

for %%f in (*.EPL) do (
  ren %%~nf%%~xf fb!fileNum!%%~xf
  set/a fileNum += 1
)

I can make it rename numerically and it actually works but I can't add the leading zeroes at all, all my attempts lead to it renaming only one file and leaving the rest

DniweTamp
  • 25
  • 3

2 Answers2

0

The following would be my suggestion:

Please note however, that the example does not cater for any existing filenames in the directory which already match fb<num><num><num>.EPL, so those will also be renamed with possible new numbers too.

@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "SourceDir=."
Set "FileGlob=*.EPL"
Set "Prefix=fb"
Set "FileNum=1000"
For /F Delims^= %%G In ('(Set PATHEXT^=^) ^& "%SystemRoot%\System32\where.exe"
 /F "%SourceDir%":"%FileGlob%" 2^> NUL') Do (Set /A FileNum += 1
    SetLocal EnableDelayedExpansion & Ren %%G "%Prefix%!FileNum:~-3!%%~xG"
    EndLocal)
  • Insert your required source directory between the = and closing " on line 3, (I've used . for the current directory, as per your example, but you can use an absolute or other relative path as needed).
  • Insert your required file glob prefix string between the = and closing " on line 4, (I've used *.EPL to match your example).
  • Insert your required file name prefix string between the = and closing " on line 5, (I've used fb to match your example).

I've used 1000 as your starting file number, because Set /A uses integers, and sees multiple concurrent 0's as just 0. Adding the 1 will prevent that, and will be omitted, when the varible expansion, uses just the last three characters. I also adjusted it so that the file numbering begins with fb001.EPL, to match your question parameters, (your code was beginning the sequence with fb000.EPL).

I've enabled delayed expansion within the loop, because it is required, when both modifying and using a variable within the same parenthesized code block. It shouldn't normally be enabled for the entire script, because filenames and strings containing ! characters can be affected, (those characters will be omitted).

I've also gone 'belt and braces' with the file selection, by using where.exe. This utility is not affected by Windows using 8.3 naming, which, whilst it may not be an issue with your provided example, will match exactly extensions .EPL, not those which begin with .EPL. Standard For loops, (which you used), and the more commonly used Dir command are both affected by 8.3 naming.

For additional robustness, I've used the full path to where.exe with the system environment variable %SystemRoot%, to prevent reliance on the %Path% variable which is often broken, by its incorrect or accidental end user modification.


As a direct resolution to your own code without modification to the majority of it:

setlocal ENABLEDELAYEDEXPANSION
set /a fileNum = 1
set fileNum=1000%fileNum%

for %%f in (*.EPL) do (
  ren "%%f" fb!fileNum:~-3!%%~xf
  set /a fileNum += 1
)

I must add however, that's because your example code is using a standard for loop, you may have issues. The problem is that a your loop will pass the first file through to the do portion whilst it is still parsing the others under the all encompassing * glob. This means that fb001.EPL will be put back into the list for parsing, and could be picked up again for processing another time, this could continue for other files too!

Compo
  • 36,585
  • 5
  • 27
  • 39
0
@ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
rem The following settings for the source directory, destination directory, target directory,
rem batch directory, filenames, output filename and temporary filename [if shown] are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.

SET "sourcedir=u:\your files\t w o"
SET /a filenumber=1001

FOR /f "delims=" %%b IN ('dir /b /a-d "%sourcedir%\*.epl" ' ) DO (
 SET "originalfilename=%%~nb"
 SET "notnumber=Y"
 rem do not rename files "fb999"
 IF /i "!originalfilename:~0,2!!originalfilename:~5!" == "fb" IF "!originalfilename:~4!" neq "" CALL :isnum !originalfilename:~2,3!
 IF defined notnumber (
  CALL :nextvalidnum
  IF NOT DEFINED filenumber ECHO Fail - no available fb999&GOTO :EOF 
  REN "%sourcedir%\%%b" "fb!filenumber:~-3!.epl"
 )
)
GOTO :EOF

:: Determine whether %1 is purely numeric
:isnum
SET "notnumber=9%1"
FOR /l %%z IN (0,1,9) DO CALL SET "notnumber=%%notnumber:%%z=%%"
GOTO :eof

:: set filenumber to next valid fb(1)999 or empty if not available
:nextvalidnum
IF %filenumber% gtr 1999 SET "filenumber="&GOTO :EOF 
IF EXIST "%sourcedir%\fb%filenumber:~-3%.epl" SET /a filenumber+=1&GOTO nextvalidnum
IF %filenumber% gtr 1999 SET "filenumber="
GOTO :eof

Setting filenumber to 1001 initially, with the expectation of using the last 4 characters as the new fb999 name.

Read each .epl name, process only those files not named fb999. This is accomplished by remembering that the first character in a string is "character 0";detecting the first 2 characters of the name are fb, there are no characters beyond the fifth, the fourth character in the filename exists and the three characters starting at character 2 are all numeric. The routine "isnum" sets notnumber to undefined if the value provided as %1 is all-numeric and defined otherwise.

If notnumber is defined, the filename is to be processed. Detect the next valid number by incrementing filenumber if the file fb+last 3 characters of "filenumber".epl exists. If filenumber exceeds 1999 then there are no available numbers. so clear filenumber and use it as a flag to show a message and exit.

Magoo
  • 77,302
  • 8
  • 62
  • 84