Home > Blockchain >  How to rename all files with " - yyyy mm dd hh mm" in file name to just the part before da
How to rename all files with " - yyyy mm dd hh mm" in file name to just the part before da

Time:03-31

I want to rename all files in current directory with removal of - yyyy mm dd hh mm from the file names.

For example (before->after):

filename - 2022 03 31 13 28->filename
a - 2022 03 31 13 28->a
b - 2022 02 28 13 28->b
c - 2022 01 03 13 28->c

I don't know how to do that with a batch script.

I have just the idea using wildcards like - ???? ?? ?? ?? ??.

CodePudding user response:

Your guess on the - ???? ?? ?? ?? ?? wild cards is good, but that will match any character, so it will also match - This is my ID 01

So using findstr's regular expression will be a little more robust (For the purpose of this demonstration, I used .txt as the extension to dir on):

@echo off
for /F "tokens=1*delims=- " %%i in ('dir /b /a-d *.txt ^| findstr /R /C:"[a-z][ ][-][ ][0-9]*[ ][0-9]*[ ][0-9]*[ ][0-9]*"') do echo ren "%%i - %%j" "%%i%%~xj"

Note 1 The above is meant for a batch-file. Should you need it to run from cmd prompt, remove one % from each set of %%

Note 2 This command will only echo the results. For it to actually perform the rename, you need to remove echo from after do

CodePudding user response:

There could be used the following batch file for this file renaming task:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "eol=| delims=" %%I in ('dir "* - ???? ?? ?? ?? ??.*" /A-D /B 2^>nul ^| %SystemRoot%\System32\findstr.exe /R /C:". - [12][09][01234567879][0123456789] [01][0123456789] [0123][0123456789] [012][0123456789] [012345][0123456789]"') do (
    set "FileName=%%~nI"
    set "FileExt=%%~xI"
    setlocal EnableDelayedExpansion
    ren "!FileName!!FileExt!" "!FileName:~0,-19!!FileExt!"
    endlocal
)
endlocal

There is executed in background with Windows installed into C:\Windows:

C:\Windows\System32\cmd.exe /c dir "* - ???? ?? ?? ?? ??.*" /A-D /B 2>nul | C:\Windows\System32\findstr.exe /R /C:". - [12][09][01234567879][0123456789] [01][0123456789] [0123][0123456789] [012][0123456789] [012345][0123456789]"

Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul and |. The redirection operators > and | must be escaped with caret character ^ on FOR command line to be interpreted as literal characters when Windows command interpreter processes this command line before executing command FOR which executes the embedded command line.

The command DIR searches

  • in the current directory
  • for just files because of option /A-D (attribute not directory)
  • matching the wildcard pattern * - ???? ?? ?? ?? ??.* which works also for files without file extension
  • and outputs just the matching file names because of option /B (bare format).

It is possible that the command DIR fails to find any file system entry matching these criteria which results in the output of an error message to handle STDERR (standard error) which is suppressed by redirecting it with 2>nul to the device NUL.

The file names are redirected with | to FINDSTR which searches for lines (file names) with a string matched by the regular expression which filters out all file names which are found by DIR using the specified wildcard pattern, but not really having date/time at end respectively before file extension in format - yyyy MM dd HH mm which means a year with century in range 1000 to 2999, a month with two digits in range 00 to 19, a day in month with two digits in range 00 to 39, an hour with two digits in range 00 to 29, and a minute with two digits in range 00 to 59. The regular expression is not perfect for date/time validation, but should be good enough for this task.

The output by FINDSTR to handle STDOUT (standard output) of background command process is captured by cmd.exe processing the batch file and FOR processes the captured lines after cmd.exe closed itself after execution of the command line finished.

The file names must be assigned completely to the loop variable I without splitting them up with using normal spaces and horizontal tabs as string delimiters and assigning just the first space/tab delimited string the loop variable I on not starting with ;. For that reason the FOR /F option eol=| redefines the end of line character from a semicolon to a vertical bar which no file name can contain ever to avoid ignoring a file name starting with a semicolon and the option delims= defines an empty list of string delimiters to turn off splitting up the lines into tokens (substrings).

The file name without file extension and the file extension are assigned to two environment variables before enabling delayed variable expansion required in this case.

Next the file is renamed with removal of the last 19 characters from file name without extension while the file extension is kept. This solution works also for file names containing a space or a hyphen left to the date/time part to remove.

Then the previous execution environment with disabled delayed variable expansion is restored to process correct also file names containing one or more exclamation marks.

Read this answer for details about the commands SETLOCAL and ENDLOCAL as there is much more than in background than just enabling/disabling delayed expansion.

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.

  • dir /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • ren /?
  • setlocal /?
  • Related