Search code examples
batch-filecmdrename

CMD batch ren according to specific list including subdirectories


it has been years for me to use cmd and I cannot remember a thing. Now I am stuck trying to batch rename a long list of directories and subdirectories according to a specific list.

What I have here is a [long] list of set folder and subfolder names (just as an example, may include files in said folders, as well)

ren "Folder\S F 1\S F 1.1" "Folder\SF 1\SF 1.1"
ren "Folder\S F 1\S F 1.2" "Folder\SF 1\SF 1.2"
ren "Folder\S F 1\S F 1.3" "Folder\SF 1\SF 1.3"
ren "Folder\S F 1\S F 1.4" "Folder\SF 1\SF 1.4"

The ren command only works in the present directory, so this creates a syntax error.

I tried using the "ren" command with a list of specific file and directory names. This resulted in syntax error since the "ren" command only calls the current directory without subdirectories.


Solution

  • The command REN does not support the new file/folder name with path as explained by the usage help output on running ren /? in a command prompt window.

    It is also not possible to rename S F 1 to SF 1 and its subfolder S F 1.1 to SF 1.1 with just one execution of command REN.

    There must be used nested FOR loops to rename all the folders to get the wanted folder names.

    A simple solution would be:

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    for /D %%G in ("Folder\? ? *") do (
        for /D %%H in ("%%G\? ? *") do for /F "tokens=1*" %%I in ("%%~nxH") do ren "%%H" "%%I%%J"
        for /F "tokens=1*" %%I in ("%%~nxG") do ren "%%G" "%%I%%J"
    )
    endlocal
    

    This code renames first the subfolders in folder S F 1 and then the folder S F 1. The code is very fast but has the disadvantage of not being fail-safe as folders to rename could be skipped by chance or folders are renamed which should not be renamed because of the wildcard pattern matched more folder names as it looks like.

    A better code for this folders renaming task is:

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    set "BaseFolder=Folder"
    for /F "delims=" %%G in ('dir "%BaseFolder%\? ? *.*" /AD-L /B /S 2^>nul ^| %SystemRoot%\System32\findstr.exe /R /C:"\\. . [0123456789][0123456789]*\.[0123456789][0123456789]*$"') do for /F "tokens=1*" %%I in ("%%~nxG") do ren "%%G" "%%I%%J"
    for /F "delims=" %%G in ('dir "%BaseFolder%\? ? *" /AD-L /B 2^>nul ^| %SystemRoot%\System32\findstr.exe /R /C:"^. . [0123456789][0123456789]*$"') do for /F "tokens=1*" %%I in ("%%~nxG") do ren "%BaseFolder%\%%G" "%%I%%J"
    endlocal
    

    The name of the folders found by the two DIR commands are verified with FINDSTR using a regular expression to make sure to rename only folders with expected naming scheme. Folders with a name not matched by the regular expression are filtered out by FINDSTR.

    No folder is skipped anymore by chance by this code because of cmd.exe processing the batch file gets in this case first all names of the folders to rename loaded into memory before starting the folder renaming process for the subfolders ending with two numbers and a dot between (lowest folder level) and when finished for the folders ending with just one number (last but one folder level).

    To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.

    • dir /?
    • echo /?
    • endlocal /?
    • findstr /?
    • for /?
    • ren /?
    • set /?
    • setlocal /?

    Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul and |. The redirection operators > and | must be escaped with caret character ^ on the two FOR command lines to be interpreted as literal characters when Windows command interpreter processes these two command lines before executing most outer command FOR which executes the embedded command line with DIR and FINDSTR with using a separate command process started in background with %ComSpec% /c and the command line within ' appended as additional arguments.