I can rename a folder of .TXT files to a lowercase extension with
ren *.TXT *.txt
But that's because I know the extension, of which there is only one. Is there a one liner for looping over a directory and changing all the extensions to lowercase?
I tried:
for %%f in (*.*) do (rename "%%f" "%%~xf")
That works...to some extent, but it also removes the filename part. D'oh!
Fail better.
@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
FOR /f "delims=" %%A IN (
'dir /b /a-d "%sourcedir%\*" '
) DO (
FOR /f "delims=" %%a IN (
'dir /b /l "%sourcedir%\%%A" '
) DO (
if "%%~xa" neq "%%~xA" ECHO REN "%sourcedir%\%%A" "%%~nA%%~xa"
)
)
GOTO :EOF
Naturally, the two nested for
commands may be compacted to a single line if desired - shown here on multiple lines for legibility.
You would need to change the setting of sourcedir
to suit your circumstances.
The required REN commands are merely ECHO
ed for testing purposes. After you've verified that the commands are correct, change ECHO REN
to REN
to actually rename the files.
Note that %%A
retains the original character-case but %%a
(a completely different variable) acquires the lower-case equivalent because of the /l
switch on the dir
command.
Following Aacini's response, more extensive testing (well, actually trying to rename files rather than just generate a rename instruction that should on first glance work) revealed this doesn't actually work, possibly because the OS sees a file being renamed to its own name (disregarding case). Hmph.
So - first step was to rename twice - first to a dummy name, and then from the dummy name to the required name.
Fine in theory. Problem was that the ~x
operator doesn't seem to consistently report the same string - almost depending on how many times it's used. So - I tried executing a subroutine, passing the "to" and "from" filenames. The subroutine seemed to have the same problems when attempting to access the name fragments of the parameters. Gloom.
So I assigned the name to a variable and tried processing that. Repeatedly remove the string before .
in the name until there are no more dots and you have the extension.
Then remove the extension from the filename, but can't use the replace-with-nothing method since the filename may be whatever.txt.txt
for instance. So lop off the last few characters one at a time within a loop for the length of the extension found+1 (for the dot).
So - if the lower-case version of the extension found is the same as the current-case version in ext2
, no rename required. Otherwise, rename to the original-case name+the lower-case extension. Via a dummy name to ensure the OS doesn't get too smart for itself.
And here's the result. Subject to unexpected results with the usual characters, of course.
@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
:choosedummy
SET "dummyname=dummyname.%random%"
IF EXIST "%sourcedir%\%dummyname%" GOTO choosedummy
FOR /f "delims=" %%A IN (
'dir /b /a-d "%sourcedir%\*" '
) DO (
FOR /f "delims=" %%a IN (
'dir /b /l "%sourcedir%\%%A" '
) DO CALL :casechg "%%a" "%%A"
)
GOTO :EOF
:casechg
SET "ext2=%~2"
SET "name2=%~2"
:ext2loop
IF "%ext2%" neq "%ext2:*.=%" SET "ext2=%ext2:*.=%"&GOTO ext2loop
:: if extension cases are identical, or no extension, skip rename
IF "%~x1" equ "" GOTO :EOF
IF "%~x1" equ ".%ext2%" GOTO :EOF
SET "lop=%ext2%"
:loploop
SET "name2=%name2:~0,-1%"
IF DEFINED lop SET "lop=%lop:~1%"&GOTO loploop
REN "%sourcedir%\%~2" "%dummyname%"
REN "%sourcedir%\%dummyname%" "%name2%%~x1"
GOTO :eof