I would like to rename every file in a directory that contains '[' or ']' characters by removing any instance of those two characters from those filenames.
I have yet to determine any way to read filenames character-by-character with a batch file.
Thanks!
You don't need to read the filename character by character. In batch you can simply replace all occurrences of a substring subs
with another substring repl
in the value of a variable %var%
with %var:subs=repl%
. As removing is the same as replacing with an empty string (in batch at least), %var:h=%
will remove all h
s from the value of the var
variable. So all you need is to store the filename in a variable and you can have the new filename without [
and/or ]
.
To iterate over all files in a directory you'll just need a FOR
loop.
So you can iterate over all files in the current directory and rename the ones with [
or ]
in their name (or both) with the following script (see edit for version which also handles names with exclamation marks):
@echo off
Setlocal EnableDelayedExpansion
FOR %%G IN (*) DO (
set "filename=%%~G"
set "filename=!filename:[=!"
set "filename=!filename:]=!"
REM Rename only if there is a difference between new filename and old filename in %%G
IF NOT "!filename!" == "%%~G" ren "%%~G" "!filename!"
)
EndLocal
exit /b 0
Because the filename
variable is set inside the FOR
block and we want to read it inside the same block, we need delayed expansion.
EDIT: As @dbenham said in comment, delayed expansion can cause problems when you have filenames containing exclamation marks !
(%%~G
will then contain a !
which normally announces a variable being expanded with delayed expansion). To solve that problem, @dbenham proposed a nice solution: enable delayed expansion only when we're about to use it i.e. inside the FOR
block, just before using the filename
variable. The !
won't poisin the value of a variable expanded with delayed expansion so !filename!
can be used without a !
being misinterpreted in its value. This also means we'll have to move EndLocal
to after we're done using delayed expansion in the FOR
block (i.e. at the end of the block) and avoid the use of %%~G
in the ren
command. The latter can be done by using a variable to hold the original name (also before enabling delayed expansion) and use delayed expansion to retrieve the original name. That variable can then actually be used to construct the new filename.
@echo off
FOR %%G IN (*) DO (
REM Set filename without delayed expansion, no misinterpreted '!' possible
set "old_filename=%%~G"
REM before using old_filename, enable delayed expansion
SetLocal EnableDelayedExpansion
set "new_filename=!old_filename:[=!"
set "new_filename=!new_filename:]=!"
REM Rename only if there is a difference between new filename and old filename in %%G
ren "!old_filename!" "!new_filename!"
REM No more delayed expansion needed in block now
EndLocal
)
exit /b 0
Also, @KlitosKyriacou pointed out the IF
was actually unnecessary: renaming a file with its original filename causes no harm. I've left it out in my 2nd version (the edit-version).