PostureOfLearning
PostureOfLearning

Reputation: 3541

Batch file - Loop directories and rename alphabetically

I'm trying write a batch script that finds all directories, and sub-directories, and renames them to a single letter of the alphabet

Here's what I have so far

@echo off
SET "alfa=0abcdefghijklmnopqrstuvwxyz"
SET count=1
FOR /D /r %%G in ("*") DO (call :subroutine "%%G")
GOTO :eof

:subroutine
 echo %count%:%1
::Get the letter from %alfa% at the index %count%
::Rename the directory %1 to the single char letter retrieved in line above
 SET /a count+=1
IF %count%==26 (
 SET /a count=1
)
 GOTO :eof

It doesn't matter what the folder is renamed to, as long as it is a) only one letter and b) a directory with the same name doesn't already exists in that directory

NOTE: There should not be more than 26 directories in a directory

Thanks for any help

Upvotes: 1

Views: 240

Answers (2)

Magoo
Magoo

Reputation: 80033

@ECHO OFF
SETLOCAL 
SET "targetdir=U:\sourcedir"
SET "alphas=a b c d e f g h i j k l m n o p q r s t u v w x y z"
:: prefix each dirname in the subtree with "#" to avoid name-clashes.
FOR /f "delims=" %%t IN ('dir /s /b /ad "%targetdir%" ^|sort /r') DO REN "%%t" "#%%~nxt"
:: Repeat scan and rename
FOR /f "delims=" %%t IN ('dir /s /b /ad "%targetdir%" ^|sort /r') DO (
 SET "renamed="
 FOR %%r IN (%alphas%) DO IF NOT defined renamed IF NOT EXIST "%%~dpt%%r" REN "%%t" "%%r"&SET "renamed=%%r"
)

GOTO :EOF

You would need to change the setting of targetdir to suit your circumstances.

First, rename every directory in the subtree b prefixing its name with some string which does not match the start of any subdirectoryname or filename. This could be made intelligent, but I simply used #.

By sorting the names in reverse-order, any subdirectory name appears before its parent, hence we will not have the situation where an attempt will be made to rename a subdirectory whose parent has changed name.

Then, using the same principle, try to change the name of the subdirectories to the single-letter as required, by checking whether there is already a subdirectory at that level with the character in question.

I'd suggest exercising this agains a dummy subtree to guage its suitability.

Upvotes: 0

Aacini
Aacini

Reputation: 67216

The solution below assume that directory names with just one char, that char is a letter. If this is not true, additional code must be inserted.

@echo off
setlocal EnableDelayedExpansion
call :treeProcess
goto :EOF


:treeProcess
set "alfa=0abcdefghijklmnopqrstuvwxyz"

rem Create "name" array with directory names
set "count=0"
for /D %%d in (*) do (
   set "dir=%%d"
   rem If dir name have more than one letter
   if "!dir:~1!" neq "" (
      rem ... insert it in "name" array
      set /A count+=1
      set "name[!count!]=%%d"
   ) else (
      rem ... remove such letter from the alfa string
      set "alfa=!alfa:%%d=!"
   )
)

rem Rename the directories from "name" array to just one letter from alfa string
for /L %%i in (1,1,%count%) do (
   ren "!name[%%i]!" "!alfa:~%%i,1!"
   set "name[%%i]="
)

rem Recursively call this subroutine to process nested directories
for /D %%d in (*) do (
    cd %%d
    call :treeProcess
    cd ..
)
exit /b

Upvotes: 1

Related Questions