Although the question is not quite clear to me, I decided to provide an answer, because the task of extracting a numeric part from the end of a string appears not to be that trivial, particularly in case both the preceding string and the numeric portions may have different lengths.
So here is a script that accepts file paths/names/patterns provided as command line arguments, splits off ther numeric part, prepends an optional prefix to it and renames the file accordingly (actually it just echoes the ren
command line for testing; remove the upper-case ECHO
to actually rename):
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "PREFIX="
for %%F in (%*) do (
for /F "tokens=1-2 delims=0123456789 eol=0" %%K in ("_%%~nF") do (
if "%%L"=="" (
set "FLOC=%%~F"
set "FILE=%%~nF"
set "FEXT=%%~xF"
set "FNEW="
setlocal EnableDelayedExpansion
set "FILE=_!FILE!"
for /L %%E in (0,1,9) do (
set "NAME=!FILE:*%%E=%%E!"
if not "!NAME!"=="!FILE!" (
if 1!NAME! GTR 1!FNEW! (
set "FNEW=!NAME!"
)
)
)
ECHO ren "!FLOC!" "!PREFIX!!FNEW!!FEXT!"
endlocal
)
)
)
endlocal
exit /B
The script skips all files that have less or more than exactly one numeric part in their names, and also those where the numeric part is followed by something other than the file name extension. For example, abcd1234.txt
is processed, whereas abcd.txt
, 1234.txt
, ab1234cd.txt
, 1234abcd.txt
and ab12cd34.txt
are skipped. Note that the numeric part is limited to nine decimal figures.
If the limit of nine digits is disturbing, the following script can be used. It is very similar to the aforementioned one, but a numeric comparison has been replaced by a string comparison with the numbers padded by leading zeroes to have equal lengths. Therefore the string comparison provides the same result as a pure numeric comparison:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "PREFIX="
set /A "DIGS=256"
setlocal EnableDelayedExpansion
for /L %%E in (1,1,%DIGS%) do set "PADZ=!PADZ!0"
endlocal & set "PADZ=%PADZ%"
for %%F in (%*) do (
for /F "tokens=1-2 delims=0123456789 eol=0" %%K in ("_%%~nF") do (
if "%%L"=="" (
set "FLOC=%%~F"
set "FILE=%%~nF"
set "FEXT=%%~xF"
set "FNEW="
setlocal EnableDelayedExpansion
set "FILE=_!FILE!"
for /L %%E in (0,1,9) do (
set "NAME=!FILE:*%%E=%%E!"
if not "!NAME!"=="!FILE!" (
set "CMPN=%PADZ%!NAME!"
set "CMPF=%PADZ%!FNEW!"
if "!CMPN:~-%DIGS%!" GTR "!CMPF:~-%DIGS%!" (
set "FNEW=!NAME!"
)
)
)
ECHO ren "!FLOC!" "!PREFIX!!FNEW!!FEXT!"
endlocal
)
)
)
endlocal
exit /B
This is a robust and more flexible approach, which allows to specify what numeric part to extract by its (zero-based) index, in the variable INDEX
(a negative value counts from the back, so -1
points to the last one, if you prefer that):
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "PREFIX=blah" & rem // (optional prefix to be used for the new file names)
set /A "INDEX=0" & rem // (`0` means first numeric part, `-1` means last one)
rem // Loop through command line arguments:
for %%F in (%*) do (
set /A "CNT=-1" & set "KIND="
for /F "delims== eol=" %%E in ('2^> nul set "$PART["') do set "%%E="
rem // Store information about currently iterated file:
set "FLOC=%%~F"
set "FILE=%%~nF"
set "FEXT=%%~xF"
rem // Toggle delayed expansion to avoid troubles with `!`:
setlocal EnableDelayedExpansion
rem // Assemble a list of file name portions of numeric and non-numeric parts:
set "LIST= "!FILE!" "
for /L %%J in (0,1,9) do set "LIST=!LIST:%%J=" %%J "!"
set "LIST=!LIST: "" =!"
rem // Determine file name portions, together with their count and kinds:
for %%I in (!LIST!) do (
endlocal & set /A "CNT+=1"
set "ITEM=%%~I" & set "TEST=%%I"
setlocal EnableDelayedExpansion
if "!TEST!"=="!ITEM!" (set "KND=0") else (set "KND=-")
for /F %%K in ("KIND=!KIND!!KND!") do (
for /F "delims=" %%E in ("$PART[!CNT!]=!ITEM!") do (
endlocal & set "%%K" & set "%%E"
)
)
setlocal EnableDelayedExpansion
)
rem // Retrieve the desired numeric file name portion:
if %INDEX% lss 0 (set /A "INDEX=-(1+INDEX)")
if %INDEX% lss 0 (set "RANGE=!CNT!,-1,0") else (set "RANGE=0,1,!CNT!")
set /A "IDX=-1" & set "FNEW=" & for /L %%J in (!RANGE!) do (
if "!KIND:~%%J,1!"=="0" set /A "IDX+=1" & (
if !IDX! equ !INDEX! for %%I in (!IDX!) do set "FNEW=!$PART[%%J]!"
)
)
rem // Actually rename file:
if defined FNEW (
ECHO ren "!FLOC!" "!PREFIX!!FNEW!!FEXT!"
)
endlocal
)
endlocal
exit /B