I have copied files from an old backup where all the files have been appended with a timestamp of the backup so a file that was previously called "background.jpg" has now been named "background (2022_12_15 14_28_40 UTC).jpg" in the backup. I would like to remove all of these timestamps from where they occur in these filenames, restoring the filenames back to what they were originally.
I found a very similar question here: Using CMD on Windows to remove a specific substring from a directory of files
However, I had difficulty with both of the answers here. The shorter, one-line script, I tried running like this:
cmd /v:on /c "for /R %f in (* ^(2022_12_15 14_28_40 UTC^).*) do @set "nn=%~nf" & echo ren "%~ff" "!nn:~0,-26!%~xf""
(In the above code, including "echo" previews the rename (ren) operation without actually doing it, while omitting "echo" actually executes the series of renames.) I had to escape the parentheses in the substring to get it to run without an .*) was unexpected at this time
error. But it didn't work correctly -- rather than focus only on files with the substring specified, it applied this operation to all files, which did fix all the files with the substring, but it also caused some problems because it wiped out the filename of files without this substring and which were 26 characters or shorter. Also, there were these erroneous rename commands added for the top level folder and each subfolder within:
ren "C:\Users\[folder or subfolder]\(2022_12_15" ""
ren "C:\Users\[folder or subfolder]\14_28_40" ""
There are no such files in any of the folders or subfolders with just that name. Looking at this while writing this question, it looks like CMD is interpreting this fileset as "*" AND "(2022_12_15" AND "14_28_40" AND "UTC).*", which explains that fileset it decided on, but I couldn't figure out how to get spaces to not register as separating different tokens that way but rather part of the filename specification itself (escaping with ^ didn't work). Some help?
I also tried Mofi's answer, but with some adjustments made to work with my particular substring:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "delims=" %%I in ('dir "%~dp0* (2022_12_15 14_28_40 UTC).*" /A-D /B /S 2^>nul') do (
set "FullFileName=%%I"
set "FileNameOnly=%%~nI"
set "FileExtension=%%~xI"
setlocal EnableDelayedExpansion
if /I "!FileNameOnly:~-26!" == " (2022_12_15 14_28_40 UTC)" ren "!FullFileName!" "!FileNameOnly:~0,-26!!FileExtension!"
endlocal
)
endlocal
(My file looks like above except with a lot of comments inserted as notes to explain to myself what was going on.)
But using the above, I run into some issues. When I run it just like above, I get this error:
. was unexpected at this time.
Which I think happens on the "for" line, since echos above print out but echos below do not, although I think I may not understand how echos work in Windows batch files because: when I change nothing except add an echo following the "for ... do (" line:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "delims=" %%I in ('dir "%~dp0* (2022_12_15 14_28_40 UTC).*" /A-D /B /S 2^>nul') do (
echo I1: %%I
set "FullFileName=%%I"
set "FileNameOnly=%%~nI"
set "FileExtension=%%~xI"
setlocal EnableDelayedExpansion
if /I "!FileNameOnly:~-26!" == " (2022_12_15 14_28_40 UTC)" ren "!FullFileName!" "!FileNameOnly:~0,-26!!FileExtension!"
endlocal
)
endlocal
I get this output and the program continues:
I1: C:\Users\[filepath redacted]\background (2022_12_15 14_28_40 UTC).jpg
The system cannot find the drive specified.
The system cannot find the drive specified.
I don't understand why adding an echo here changes the behavior of the program.
When the program continues, it doesn't make any changes to files. I've done some testing and it seems that the IF check fails. However, the logic of the if and rename operations seems sound because if I hardcode the three variables -- FullFileName, FileNameOnly, and FileExtension -- to be the expected values for a specific file:
set "FullFileName=C:\Users\[filepath redacted]\background (2022_12_15 14_28_40 UTC).jpg"
set "FileNameOnly=background (2022_12_15 14_28_40 UTC)"
set "FileExtension=.jpg"
Then this script renames the file as expected. If I echo the rename operation like this, this is what I get:
echo ren "!FullFileName!" "!FileNameOnly:~0,-26!!FileExtension!"
Prints:
ren "C:\Users\[filepath redacted]\background (2022_12_15 14_28_40 UTC).jpg" "background.jpg"
Also, there are many files in this folder and its subfolders, but the file being singled out by this script (after I add the above echo) is correctly the only file with this substring in the filename.
But using the set commands above does not trigger the IF in the same way these manual sets do. When I try to print out %%I later in the script, I never again get the value that was printed out the first time I echo'd:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "delims=" %%I in ('dir "%~dp0* (2022_12_15 14_28_40 UTC).*" /A-D /B /S') do (
echo I1: %%I <-- prints "I1: C:\Users\[filepath redacted]\background (2022_12_15 14_28_40 UTC).jpg"
set "FullFileName=%%I"
set "FileNameOnly=background (2022_12_15 14_28_40 UTC)"
set "FileExtension=.jpg"
echo I2: %%I <-- prints "I2: %I"
setlocal EnableDelayedExpansion
if /I "!FileNameOnly:~-26!" == " (2022_12_15 14_28_40 UTC)" (
:: The code goes into the IF here because of the hardcoded variables above.
echo I3: %%I <-- prints "I3: %I"
echo ren "!FullFileName!" "!FileNameOnly:~0,-26!!FileExtension!" <-- prints "ren "%I" "background.jpg"
)
endlocal
)
endlocal
I'm just so stuck and I need help. I don't know how to actually set the local variables properly using the for loop variable %%I
. I don't understand why this script won't work, and I don't understand why inserting an echo temporarily fixed it (but the variable-setting still won't work). Does this have something to do with the parentheses in my substring? With the spaces? I would just appreciate some help on how to fix up either the one-line code so that it targets the correct fileset, or fix up the more complicated batch file so that the for and set lines work properly.