简体   繁体   中英

Windows batch script to renumber files in folder

I have a folder with files that are (ideally) sequentially named. But sometimes I want to add a new file into the sequence, which I do by appending a letter, so that it still sorts in the right order, eg

顺序正确但未按顺序编号

I want a batch that renames these back into a proper sequence, ie P01.svg , P02.svg , P03.svg , etc. Of course, the correct order must be preserved in the process.

I've tried various things, but can't find a solution that preserves the order... sometimes the renaming appears to be done in the wrong order so that the files get out of sequence. My latest attempt is:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
REM first rename with xxx prefix to avoid name clashes, then do a second loop to remove the xxx prefix
set /a i=1
for /f "delims=" %%a in ('dir *.svg /b /a-d-h-s') do (
    set "p=0!i!"
    ren "%%a" "xxxP!p:~-2!.svg"
    set /a i = i + 1
)
REM second loop...
set /a i=1
for /f "delims=" %%a in ('dir *.svg /b /a-d-h-s') do (
    set "p=0!i!"
    ren "%%a" "P!p:~-2!.svg"
    set /a i = i + 1
)

Why are the renamed files not in the correct order every time?

You don't need you first loop. A simple ren command is sufficient.

For the correct order (by name), just expand the dir command with the /on option (" O rder by N ame")

@echo off
setlocal enabledelayedexpansion
ren *.svg *.svg.tmp
set nr=100
for /f "delims=" %%a in ('dir /b /a-d-h-s /on *.svg.tmp') do (
  set /a nr+=1
  ECHO ren "%%a" "P!nr:~-2!.svg"
)

Note: I disabled the ren command for security reasons. When the output fits your needs, just remove the ECHO

You do not need to use two loops and neither do you have to rename the files twice. If you simply count the number of files in advance and then rename then in descending order (hence from highest to lowest) there should not be any collisions possible, given that the files have got consecutive numbers (no gaps allowed).

Here is a script that does exactly this (see all the explanatory rem remarks in the code):

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_ROOT="  & rem /* (root directory; empty or `.` is current,
                rem     `%~dp0.` is location of this script) */
set "_PREF=P" & rem // (desired file name prefix)
set "_MASK=%_PREF%*.svg" & rem // (search pattern for files)
set /A "_DIGS=2" & rem // (number of digits in the new names)

rem // Get limit of number of files that can be handled:
set /A "CNT=1" & for /L %%D in (1,1,%_DIGS%) do set /A "CNT*=10"
rem // Change into root directory:
pushd "%_ROOT%" && (
    rem // Count number of matching files, quit if there are too many:
    for /F %%C in ('dir /B /A:-D-H-S "P*.svg" ^| find /C /V ""') do (
        set /A "CNT+=%%C" & if %%C geq %CNT% exit /B 2
    )
    rem /* List files sorted in descending order by name and prepend
    rem    with an ascending index number: */
    for /F "tokens=1* delims=:" %%E in ('
        dir /B /A:-D-H-S /O:-N "P*.svg" ^| findstr /N "^"
    ') do (
        rem /* Split off the index number and determine the new number
        rem    to be used in the new file name: */
        set /A "FNUM=CNT-%%E+1"
        rem // Store the current file base name and extension:
        set "FILE=%%~nF" & set "FEXT=%%~xF"
        setlocal EnableDelayedExpansion
        rem // Actually rename the file:
        ECHO ren "!FILE!!FEXT!" "!_PREF!!FNUM:~-%_DIGS%!!FEXT!"
        endlocal
    )
    popd
)

endlocal
exit /B

After having tested for the correct output, remove the upper-case ECHO command !


This is an approved variant that can even handle collisions (meaning a file with a new name already exists), which may occur when there are gaps in the original (numeric) sequence of file names; in such cases, an additional suffix .tmp is temporarily appended and after having processed all files that suffix becomes removed by a single ren command:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_ROOT="  & rem /* (root directory; empty or `.` is current,
                rem     `%~dp0.` is location of this script) */
set "_PREF=P" & rem // (desired file name prefix)
set "_MASK=%_PREF%*.svg" & rem // (search pattern for files)
set "_SUFF=.tmp" & rem // (temporary suffix to handle collisions)
set /A "_DIGS=2" & rem // (number of digits in the new names)

rem // Get limit of number of files that can be handled:
set /A "CNT=1" & for /L %%D in (1,1,%_DIGS%) do set /A "CNT*=10"
rem // Change into root directory:
pushd "%_ROOT%" && (
    rem // Terminate if there are files with the temporary suffix:
    if defined _SUFF if exist "%_MASK%%_SUFF%" popd & exit /B 3
    rem // Count number of matching files, quit if there are too many:
    for /F %%C in ('dir /B /A:-D-H-S "P*.svg" ^| find /C /V ""') do (
        set /A "CNT+=%%C" & if %%C geq %CNT% popd & exit /B 2
    )
    rem /* List files sorted in descending order by name and prepend
    rem    with an ascending index number: */
    for /F "tokens=1* delims=:" %%E in ('
        dir /B /A:-D-H-S /O:-N "P*.svg" ^| findstr /N "^"
    ') do (
        rem /* Split off the index number and determine the new number
        rem    to be used in the new file name: */
        set /A "FNUM=CNT-%%E+1"
        rem // Store the current file base name and extension:
        set "FILE=%%~nF" & set "EXTF=%%~xF" & set "EXTT="
        setlocal EnableDelayedExpansion
        rem /* Actually rename the file; in case of collisions, append
        rem    another suffix to the name and rename again later: */
        set "NAME=!_PREF!!FNUM:~-%_DIGS%!!EXTF!"
        if /I not "!FILE!!EXTF!"=="!NAME!" (
            if exist "!NAME!" set "EXTT=!_SUFF!"
            ECHO ren "!FILE!!EXTF!" "!NAME!!EXTT!"
        )
        endlocal
    )
    rem // Resolve potential collisions, so remove additional suffixes:
    setlocal EnableDelayedExpansion
    if defined _SUFF if exist "!_MASK!!_SUFF!" ren "!_MASK!!_SUFF!" "*."
    endlocal & popd
)

endlocal
exit /B

Again remove the upper-case ECHO command to actually rename files!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM