How to Delete Files Older Than X Days in Batch Script
Automated cleanup is a cornerstone of system maintenance. Scripts that remove old log files, temporary data, or outdated backups are essential for managing disk space and keeping directories tidy. Windows provides a powerful, built-in command-line utility called ForFiles specifically for this purpose, allowing you to select and act on files based on their age.
This guide will teach you how to use the ForFiles command to safely identify and delete files older than a specified number of days, how to include subdirectories in your search, and how to correctly handle paths that contain spaces.
The Core Command: ForFiles
The ForFiles command is a versatile utility designed to select a group of files and execute a command on them. Its most powerful feature is its ability to filter files based on their last modified date.
The basic syntax for a delete operation is:
ForFiles /P "Path" /D -NumberOfDays /C "cmd /c del @path"
/P: Specifies the path to start searching./D: Specifies the date criteria. A negative number (-30) means "older than 30 days."/C: Specifies the command to run on each file found.@pathis a variable representing the full path of the file.
Safety First: Listing Files Before Deleting
Never run a delete command without first testing it. A small mistake in your path or date criteria could cause irreversible data loss. The safest way to test is to replace the delete command with an ECHO command. This will show you exactly which files your command would delete.
Let's find all .log files in C:\Logs that are older than 30 days.
@ECHO OFF
ECHO The following files are older than 30 days and would be deleted:
ForFiles /P "C:\Logs" /M "*.log" /D -30 /C "cmd /c ECHO @path"
The /M "*.log" parameter is a search mask to target only files ending with .log.
Output (This command doesn't delete anything. It simply lists the files that match the criteria.)
The following files are older than 30 days and would be deleted:
"C:\Logs\2023-08-15-app.log"
"C:\Logs\2023-08-21-security.log"
Once you have verified that the list is correct, you can proceed to the actual delete command.
Executing the Delete Command
After a successful dry run, you can replace the ECHO command with the del command.
Script: The Real Delete
@ECHO OFF
ECHO Deleting .log files older than 30 days in C:\Logs...
ForFiles /P "C:\Logs" /M "*.log" /D -30 /C "cmd /c del @path"
ECHO Cleanup complete.
This command will find the same files as the dry run, but this time it will execute del "C:\Logs\..." for each one, permanently removing them.
Key ForFiles Parameters Explained
Understanding the main parameters is key to using ForFiles effectively.
/P <Path>: The starting directory for the search./S: Recursive. MakesForFilessearch into all subdirectories./M <SearchMask>: The file pattern to search for (e.g.,*.tmp,backup_*.zip). The default is*.*./D <Date>: The date filter./D -30: Finds files with a last modified date 30 days ago or earlier./D +30: Finds files with a last modified date 30 days from now or later./D +10/27/2023: Finds files modified on or after a specific date.
/C "<Command>": The command to execute. This string is executed for each matching file.@file: The filename without the extension.@fname: The filename with the extension.@ext: The file's extension.@path: The full path of the file.@relpath: The relative path of the file.
Common Pitfalls and How to Solve Them
Problem: Command Fails on Paths with Spaces
If a filename or path contains spaces, a simple del @path can fail because the command processor gets confused.
Let's see the error. If @path expands to "C:\My Logs\old log.txt", the command becomes del "C:\My Logs\old log.txt", which is often misinterpreted.
Solution: Add Escaped Quotes
The most robust way to handle this is to add escaped quotes \" around the @path variable within the command string.
REM This command correctly handles spaces in filenames and paths.
ForFiles /P "C:\My Logs" /D -30 /C "cmd /c del \"@path\""
This ensures the command executed is cmd /c del "\"C:\My Logs\old log.txt\"", which is parsed correctly.
Problem: Deleting Files in Subdirectories (Recursive Delete)
By default, ForFiles only searches the directory specified in /P. It does not look inside subfolders.
Solution: Use the /S Switch
The /S switch tells ForFiles to recurse into all subdirectories. This is perfect for cleaning up an entire directory tree.
Let's do a recursive dry run first to find all .tmp files older than 7 days in a user's AppData\Local\Temp folder and all its subfolders.
@ECHO OFF
ECHO The following files in the temp folder tree would be deleted:
ForFiles /P "%LOCALAPPDATA%\Temp" /S /M "*.tmp" /D -7 /C "cmd /c ECHO @path"
After verifying the output, you can switch ECHO @path to del \"@path\".
Practical Example: A Daily Log Cleanup Script
This script is a complete, reusable solution for cleaning up a log directory. It uses variables for easy configuration and includes the best practices discussed.
@ECHO OFF
SETLOCAL
REM --- Configuration ---
SET "TARGET_FOLDER=E:\Application\Logs"
SET "FILE_MASK=*.log"
SET "MAX_AGE_DAYS=14"
ECHO --- Log Cleanup Script ---
ECHO.
ECHO Target Folder: %TARGET_FOLDER%
ECHO File Mask : %FILE_MASK%
ECHO Max Age : %MAX_AGE_DAYS% days
ECHO.
IF NOT EXIST "%TARGET_FOLDER%" (
ECHO [ERROR] Target folder not found. Aborting.
GOTO :End
)
REM --- Dry Run First (Comment this out to enable deletion) ---
ECHO [DRY RUN] The following files WOULD be deleted:
ForFiles /P "%TARGET_FOLDER%" /S /M "%FILE_MASK%" /D -%MAX_AGE_DAYS% /C "cmd /c ECHO @path"
GOTO :End
REM --- Actual Delete Command (Uncomment to enable) ---
REM ECHO [DELETING] Removing old files...
REM ForFiles /P "%TARGET_FOLDER%" /S /M "%FILE_MASK%" /D -%MAX_AGE_DAYS% /C "cmd /c del /F /Q \"@path\""
REM ECHO Deletion complete.
:End
ENDLOCAL
ECHO Script finished.
del /F /Q is added to the final command to force-delete read-only files (/F) and do so quietly without prompting (/Q).
Conclusion
The ForFiles command is the definitive Windows tool for managing files based on their age. It provides a powerful and flexible way to automate cleanup tasks that would otherwise be tedious and manual.
To ensure your cleanup scripts are safe and effective:
- Always perform a dry run by using
ECHO @pathbefore running the actualdelcommand. - Use the
/Sswitch to include subdirectories in your search. - Properly quote paths and use
\"@path\"to handle spaces in filenames gracefully.
By mastering ForFiles, you can create reliable, set-and-forget scripts to keep your systems clean and organized.