Using CMD on Windows to remove a specific substring from a directory of files

Viewed 2208

I frequently use a free online lossless file compressor to save space on my disk and make transferring and pushing repos easier. My main problem with the compressor is it appends "-min" to the end of every filename. For various reasons, I want to replace the original files by overwriting them; instead of deleting the old files and keeping the new files (with the "new" names).

For my PDF directory, I tried this: FOR /R %f IN (*-min.pdf) DO REN "%f" *.pdf

And it seems to correctly find all the corresponding files, but their names remain the same. What am I doing incorrectly? Is there a single command that would be file-format-agnostic, so I wouldn't have to sub out the file extension for txt's, png's, etc?

I just need it to remove the -min from the end of each filename (before the file extension).

2 Answers

FOR /R %f IN (*-min.pdf) DO REN "%f" *.pdf

For a one liner (at the cmd prompt) remove echo from the following.

cmd /v:on /c "for /R %f in (*-min.pdf) do @set "nx=%~nxf" & echo ren "%~ff" "!nx:-min.pdf=.pdf!""

The above can be easily changed to perform other string manipulations, but it is not technically foolproof, for example it will rename a file named "a-min.pdf.b-min.pdf-c-min.pdf" to "a.pdf.b.pdf-c.pdf.". If that is a concern in this case, then use the following, which is essentially the same as in @Mofi's answer.

cmd /v:on /c "for /R %f in (*-min.pdf) do @set "nn=%~nf" & echo ren "%~ff" "!nn:~0,-4!%~xf""

The task can be done with a batch file with following command lines:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "delims=" %%I in ('dir "%~dp0*-min.*" /A-D /B /S 2^>nul') do (
    set "FullFileName=%%I"
    set "FileNameOnly=%%~nI"
    set "FileExtension=%%~xI"
    setlocal EnableDelayedExpansion
    if /I "!FileNameOnly:~-4!" == "-min" ren "!FullFileName!" "!FileNameOnly:~0,-4!!FileExtension!"
    endlocal
)
endlocal

The command DIR executed by a separate command process started by FOR in background with %ComSpec% /c and the command line between ' appended as additional arguments outputs also file names like Test-File!-min.x.pdf with full path. For that reason the IF condition makes sure to rename only files of which file name really ends case-insensitive with the string -min like Test-File!-MIN.pdf.

Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • call /? ... explains %~dp0 ... drive and path of argument 0 which is full path of the batch file which always ends with a backslash and for that reason concatenated with the wildcard pattern *-min.* without an additional backslash. %~dp0 can be removed to run DIR on current directory and all its subdirectories instead of batch file directory and all its subdirectories.
  • dir /?
  • echo /?
  • endlocal /?
  • if /?
  • ren /?
  • set /?
  • setlocal /?

See also this answer for more details about the commands SETLOCAL and ENDLOCAL.

Related