Search code examples
windowsbatch-filecmdfile-rename

CMD to iterate and recursively rename all filenames and append the current subdirectory folder to the current filename


This command in cmd renames all files in the current directory

for /f "tokens=*" %a in ('dir /b') do ren "%a" "00_%a"

But I need to get the current subdirectory name (folder name only) and append that to the %a

It should loop through all the subdirectories in the parent folder.

I have Path C:\Temp\Photos_ToRename with following folders and files

NVA-1234 (this is a subdirectory name)
--- IMG_0999.jpg (rename to NVA-1234_IMG_0999.jpg)
--- IMG_0989.jpg (rename to NVA-1234_IMG_0989.jpg)
--- IMG_0979.jpg (rename to NVA-1234_IMG_0979.jpg)

NVS-3456 (this is a subdirectory name)
--- IMG_1999.jpg (rename to NVS-3456_IMG_1999.jpg)
--- IMG_1989.jpg (rename to NVS-3456_IMG_1989.jpg)
--- IMG_1979.jpg (rename to NVS-3456_IMG_1979.jpg)

NVS-3359 (this is a subdirectory name)
--- IMG_2999.jpg (rename to NVS-3359_IMG_2999.jpg)
--- IMG_2989.jpg (rename to NVS-3359_IMG_2989.jpg)
--- IMG_2979.jpg (rename to NVS-3359_IMG_2979.jpg)

.....


Solution

  • This should do the trick without string manipulation and with iteration of the needed directory hierarchy depth only ‐ code for direct usage in Command Prompt:

    for /D %J in ("C:\Temp\Photos_ToRename\*") do @pushd "%~J" && ((for /F "delims= eol=|" %I in ('dir /B /A:-D-H-S "*.jpg"') do @ren "%I" "%~nxJ_%I") & popd)
    

    Code for usage within a batch file (with comments):

    @echo off
    rem // Iterate only the required directory hierarchy depth:
    for /D %%J in ("C:\Temp\Photos_ToRename\*") do (
        rem // Change into the currently iterated sub-directory:
        pushd "%%~J" && (
            rem /* Iterate through matching files; the `for /F` loop together with `dir` is
            rem    mandatory here and cannot be replaced by a simple standard `for` loop like
            rem    `for %%I in ("*.jpg") do`, because then, files might become renamed twice
            rem    since `for` does not build the complete file list prior to looping, but
            rem    `for /F` does as it awaits the full output of the `dir` command: */
            for /F "delims= eol=|" %%I in ('dir /B /A:-D-H-S "*.jpg"') do (
                rem // Actually rename the currently iterated file:
                ren "%%I" "%%~nxJ_%%I"
            )
            rem // Return from sub-directory:
            popd
        )
    )