It makes absolutely no sense to first move files from drive D:
to drive E:
which requires copying the data of each file, and then delete each file on drive E:
. It is much faster to delete the files older than 29 days directly on drive D:
.
The batch file below can be used for the file deletion task with logging success or error of each file deletion.
@echo off
if "%~1" == "" goto RunForFiles
del /A /F %1 2>nul
(if not exist %1 (echo %DATE% %TIME% Deleted successfully: %1) else echo %DATE% %TIME% Failed to delete file: %1)>>"E:\LogStoragePath\OldFileDeletionLog.txt"
exit /B
:RunForFiles
md "E:\LogStoragePath" 2>nul
del "E:\LogStoragePath\OldFileDeletionLog.txt" 2>nul
%SystemRoot%\System32\forfiles.exe /P "D:\Test" /M *.* /S /D -30 /C "%SystemRoot%\System32\cmd.exe /D /S /C \"if @isdir == FALSE \"%~f0\" @path\""
The batch file first checks if being call without any argument which is the case on batch file being started by the scheduled task. In this case processing the batch file continues with the lines below the label RunForFiles
.
There is first created the directory (tree) to the log file without checking if that could be done successfully at all. The error message output by command MD on log file directory existing already is suppressed by redirecting it from handle STDERR to device NUL. 2>nul
suppresses also the error message output on creation of directory (tree) due to other reasons like missing permissions on storage media to do that.
Next the log file existing perhaps from a previous execution is deleted with suppressing with 2>nul
the error message output by DEL if the log file does not exist at all or the deletion could not be done because of missing permissions to do that (NTFS permissions, read-only attribute, log file currently opened in an application).
Then FORFILES is executed to search in
- directory
D:\Test
specified with path option /P
- and all its subdirectories because of option
/S
- for file system entries (directories, files and reparse points)
- matching the wildcard pattern
*.*
(any) specified with mask option /M
- with a last modification date less than or equal 30 days
- to execute the command specified with option
/C
.
The command results in running one more Windows Command Processor with the options /D
to ignore the AutoRun
registry value and /S
to interpret everything after next option /C
as one argument string with the command line to execute and option /C
to execute the command line specified next and close itself after finishing the execution.
The started Windows Command Processor process first checks with a case-sensitive string comparison if the current file system entry found by FORFILES with a last modification date older than 29 days is not a directory. A directory is ignored and results in an immediate close of started cmd.exe
.
For a file is executed next by started cmd.exe
the currently processed batch file with the full file name enclosed in "
as argument. So the batch file processed by cmd.exe
runs forfiles.exe
which starts one more cmd.exe
to process the same batch file, but this time with a file name as argument for the batch file.
This time the batch file processing continues on third command line which uses the command DEL with option /A
(all attributes) to overrule the implicit default /A-H
(all attributes except hidden attribute) to delete also a file with hidden attribute set and option /F
to force a deletion of a file with read-only attribute set.
The file deletion is in most cases most likely successful. But an application having currently opened a file older than 29 days or special NTFS permissions can result in a failed file deletion.
Therefore an IF condition is used to verify if the file really does not exist anymore in which case a success message is output to handle STDOUT using command ECHO with the dynamic variables DATE
and TIME
. Otherwise on failed deletion of the file a failed message is output with ECHO with DATE
and TIME
to handle STDOUT. The output message is redirected to the specified log file and being appended on this log file which is opened, modified and closed for each file to delete.
Last the execution of the batch file to delete an old file is exited with command EXIT using option /B
to just exit the batch file processing and not entire cmd.exe
processing this batch file. cmd.exe
started by forfiles.exe
has nothing more to do and closes which results in forfiles.exe
searching for next file system entry matching the specified criteria.
The entire file deletion task is horrible slow using this batch file. It would be definitely much better to use for this task a small PowerShell script processed by Windows PowerShell which would do this file deletion task much faster.
I recommend to read also the chapter Best and simple backup deletion concept in my answer on Bat file to delete files only when younger files are present. It is in general not advisable to simply delete all files older than X days without checking if younger files are present, especially if the files to delete are backup files or log files of a periodically executed task. The solution posted in referenced answer using a different deletion strategy than just last modification date is also much faster than the solution posted here.
Here is also a variant of above with first moving each old file from D:\Test
and its subdirectories to E:\Test1
without replicating the directory tree in destination directory with logging success or failure of file movement and finally deleting all files in E:\Test1
recording also success or failure of file deletion. File deletion failure is very unlikely.
@echo off
if "%~1" == "" goto RunForFiles
move /Y %1 "E:\Test1\" >nul 2>nul
(if not exist %1 (echo %DATE% %TIME% Moved successfully: %1) else echo %DATE% %TIME% Failed to move file: %1)>>"E:\LogStoragePath\OldFileMoveLog.txt"
exit /B
:RunForFiles
md "E:\Test1" 2>nul
md "E:\LogStoragePath" 2>nul
del "E:\LogStoragePath\OldFileMoveLog.txt" 2>nul
%SystemRoot%\System32\forfiles.exe /P "D:\Test" /M *.* /S /D -30 /C "%SystemRoot%\System32\cmd.exe /D /S /C \"if @isdir == FALSE \"%~f0\" @path\""
set "ProcessedFile="
(echo %DATE% %TIME%
for %%I in ("E:\Test1\*") do (
set "ProcessedFile=1"
del /A /F "%%I" 2>nul
if not exist "%%I" (echo Deleted successfully: %%~nxI) else Failed to delete file: %%~nxI
))>"E:\LogStoragePath\OldFileDeletionLog.txt"
if exist "E:\LogStoragePath\OldFileDeletionLog.txt" if not defined ProcessedFile del "E:\LogStoragePath\OldFileDeletionLog.txt"
The last command line deletes the file deletion log file on being created but containing just date and time because of no file was moved before and so no file needed to be deleted at all.
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.
cmd /?
del /?
echo /?
exit /?
for /?
forfiles /?
goto /?
if /?
md /?
move /?
set /?
See also the Microsoft documentation about Using command redirection operators.