The file moving task with renaming the file with date in file name reformatted can be done with following batch file:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "BaseFolder=C:\ABC"
set "!Jan=01"
set "!Feb=02"
set "!Mar=03"
set "!Apr=04"
set "!May=05"
set "!Jun=06"
set "!Jul=07"
set "!Aug=08"
set "!Sep=09"
set "!Oct=10"
set "!Nov=11"
set "!Dec=12"
for /F "eol=| delims=" %%G in ('dir "%BaseFolder%\* - * * * * * * - * * * *, *.txt" /A-D-H /B 2^>nul') do for /F "eol=| tokens=1,7,12-14 delims=, " %%H in ("%%G") do for /F "tokens=2 delims==" %%# in ('set !%%J 2^>nul') do md "%BaseFolder%\DEF" 2>nul & move /Y "%BaseFolder%\%%G" "%BaseFolder%\DEF\%%H_%%I_%%#%%K%%L" >nul
endlocal
The first two command lines define completely the required execution environment.
There is next defined the path to base folder with the text files to move into a subfolder of the base folder assigned to environment variable BaseFolder
.
The next command lines define environment variables with abbreviated month as name preceded with !
and their corresponding two digit numbers as values.
The first FOR loop starts in background one more cmd.exe
with option /c
and the command line specified within '
appended as additional arguments to search in base folder with a wildcard pattern for the text files to move. The output of DIR to handle STDOUT (standard output) of the cmd.exe
process started in background is captured by cmd.exe
processing the batch file. The captured lines are the file names of all non-hidden *.txt
files matched by the wildcard pattern.
The first FOR loop processes one line after the other after started cmd.exe
terminated itself. There is by default first split up each line into substrings using normal space and horizontal tab as string delimiters. If the first substring starts with a semicolon, the line is ignored for further processing. Otherwise the first substring is assigned to the specified loop variable and FOR executes the commands specified next. This behavior is not wanted here as the file names definitely contain spaces and it is perhaps even possible that a file name starts with a semicolon. For that reason the option eol=|
is used to define the vertical bar as end of line character which no file name can contain ever and option delims=
is used to specify an empty list of string delimiters to disable the line splitting behavior. So the entire file name as output by DIR without path is assigned to the loop variable G
.
The second FOR processes the file name string with file extension. This time the splitting behavior is wanted using comma and normal space as string delimiters as there are of interest the following substrings:
- The first substring
abcdef
referenced with tokens=1
assigned to the specified loop variable H
.
- The seventh substring
xxxx
referenced with 7
in the tokens=
option string assigned to next loop variable I
according to the ASCII table.
- The twelfth substring
Sep
referenced with 12
in the tokens=
option string assigned to next but one loop variable J
.
- The thirteenth substring
21
referenced with -
between 12
and 14
in the tokens=
option string assigned to loop variable K
.
- The fourteenth substring
2021.txt
referenced with 14
in the tokens=
option string assigned to loop variable L
.
The file names contain perhaps one or more !
and for that reason it is better to avoid the usage of referencing environment variables which would require the usage of delayed expansion. There are also not many files to process per weekday.
For that reason the two digit number of the abbreviated month in file name is get by using one more FOR command to run in background cmd.exe
with option /c
and the command SET with the abbreviated month as environment variable name with a preceding !
. The command SET outputs to handle STDOUT of the background command process all environment variables starting with an exclamation mark and the abbreviated month. The exclamation mark is just for avoiding getting output by chance another environment variable of which name starts also with the three characters of the current month abbreviation. Environment variable names usually do not start with an exclamation mark, at least not any predefined Windows environment variable.
SET outputs the variable name, an equal sign and the assigned value. This output is captured and processed by the third FOR using this time the equal sign as delimiter and getting assigned to specified loop variable #
just the two digit number after the equal sign.
So there are now all substrings assigned to loop variables needed in new file name.
Therefore the command MD is executed to create the destination directory if not yet existing with suppressing the error message on already existing by redirecting the error message from handle STDERR (standard error) to device NUL.
Next is executed independent on result of command MD the command MOVE to move the file in base folder with file name and extension assigned to loop variable G
of first FOR to the destination folder with the new file name being concatenated with the substrings determined by second and third FOR. The message output of the successful movement of one file is suppressed by redirecting it to the device NUL while an error message would be output into the console window.
The last command ENDLOCAL restores the initial environment.
The following batch file could be also used if drive C: is using NTFS as file system and the text files contain never an exclamation mark in their file names nor in base folder path.
@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "BaseFolder=C:\ABC"
set "Jan=01"
set "Feb=02"
set "Mar=03"
set "Apr=04"
set "May=05"
set "Jun=06"
set "Jul=07"
set "Aug=08"
set "Sep=09"
set "Oct=10"
set "Nov=11"
set "Dec=12"
md "%BaseFolder%\DEF" 2>nul
for %%G in ("%BaseFolder%\* - * * * * * * - * * * *, *.txt") do for /F "eol=| tokens=1,7,12-14 delims=, " %%H in ("%%~nxG") do move /Y "%%G" "%BaseFolder%\DEF\%%H_%%I_!%%J!%%K%%L" >nul
endlocal
This batch file is executed faster as there are no other cmd.exe
instances started in background and the destination folder is created only once (hopefully successful). It uses delayed expansion to get the two digit number of the abbreviated month in file name and for that reason only two FOR loops are necessary:
- The first FOR loop is for accessing the file system on each iteration of this FOR loop to get next file name matching the wildcard pattern with full path directly from the file system. That works with moving files on NTFS drives, but can fail to work correct on FAT32 or exFAT drives as on FAT drives the file system entries changes with each successful movement of a file. For that reason it is in general better to get first loaded into the memory of
cmd.exe
processing the batch file the list of all files of which name matches the wildcard pattern as done by the first batch file and then process this list in memory instead of the file system entries permanently changing on each loop iteration.
- The second FOR loop is for getting the substrings from the file name needed in the new file name exactly as done also in the first batch file.
To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.
dir /?
echo /?
endlocal /?
for /?
md /?
move /?
set /?
setlocal /?
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
or set
command line with using a separate command process started in background.
See also single line with multiple commands using Windows batch file for an explanation of the operator &
.