The Forfiles command on Windows selects and executes a command on a file or set of files. Forfiles is ideal for batch processing through scripts. For instance on Windows Server systems. With Forfiles, you can run a command on or pass arguments to multiple files. For example, you could run the type command on all files in a tree with the .txt extension. Or you could execute every batch file (*.bat) on drive C, with the file name "Myinput.txt" as the first argument.

In this post you'll learn how to delete files recursively with Forfiles on Windows Server. For example, you delete files recursive if files are older than 'n' days (where n is 3, 5 or 10 days for example).

The Forfiles command syntax is:

forfiles [/p <Path>] [/m <SearchMask>] [/s] [/c "<Command>"] [/d [{+|-}][{<Date>|<Days>}]]

Forfiles on Windows works by implementing the recurse subdirectories flag on tools that are designed to process only a single file. Lets take an example I use a lot as a scheduled task, and break it down.

Using forfiles, you can easily batch delete files older than 7 days in Windows.

Forfiles batch process and delete files older than 'n' days

An example to batch delete all files older than seven days in C:\Windows\Temp:

ForFiles /S /P C:\Windows\Temp /D -7
   /C "cmd /c if @isdir==FALSE del /F /Q @file"
  • /S : Instructs forfiles to recurse into subdirectories. Like "DIR /S"
  • /P [pathname] : Indicates the path to start searching. The default folder is the current working directory (.).
  • /D [date] : Selects files with a last modified date greater than or equal to (+), or less than or equal to (-), the specified date using the "MM/dd/yyyy" format; or selects files with a last modified date greater than or equal to (+) the current date plus "dd" days, or less than or equal to (-) the current date minus "dd" days. A valid "dd" number of days can be any number in the range of 0 - 32768.
    "+" is taken as default sign if not specified.
  • /C [command] : Indicates the command to execute for each file.
    Command strings should be wrapped in double quotes. The default command is "cmd /c echo @file". The following variables can be used in the command string:
    @file - returns the name of the file.
    @fname - returns the file name without extension.
    @ext - returns only the extension of the file.
    @path - returns the full path of the file.
    @relpath - returns the relative path of the file.
    @isdir - returns "TRUE" if a file type is a directory, and "FALSE" for files.
    @fsize - returns the size of the file in bytes.
    @fdate - returns the last modified date of the file.
    @ftime - returns the last modified time of the file.

So what this example does, is delete all files older than one (1) day, in C:\Windows\Temp using Forfiles on Windows. This Forfiles command is ideal for batch processing, to delete files older than 'n' days using a .bat file.

More Windows forfiles command tips

Another great forfiles example to list files older than 3 days is:

forfiles /P Z:\devops\sites\example.org /M *.* /D -3 /C "cmd /c dir @FILE"

This command finds all files in the directory Z:\devops\sites\example.org that are older than 3 days, and does a dir command on those files.

Again /P for the path to perform the command in, /M for a searchmask (*.* for everything), /D for the last modified date, and /C the command to perform against @FILE.

Donate a cup of coffee
Donate a cup of coffee

Thank you very much! <3 ❤️

8 Comments

  1. Abhinav

    Can you please help me how can i use forfiles to delete all *.txt files (leaving directories) created more than a year but it should skip one folder lets say “abc” for deletion purpose rest all can be deleted.

  2. Ritvij Vyas

    This helped me out a lot. However, I need to delete all files and folders inside a particular directory without exception. The folders have odd file extensions, long names and some are just 1 KB.
    I used the below command
    forfiles /S /P E:\scratch /M * /D -30 /C “cmd /c if @isdir==TRUE rd /s /q @file

    But it seems to work sporadically just for some files inside the folder. Can you help me?

    • Hi Ritvij,

      The default searchmask (/M) already is *, you can leave that out. Your forfiles command should work as expected; it should delete all folders in E:\scratch that are older than 30 days.

      For testing purposes you can always echo: forfiles /S /P E:\scratch /M * /D -30 /C "cmd /c if @isdir==TRUE echo rd /s /q @file" to see what it does. And /q is nothing more than “quiet”, omit that one for more debug output.

  3. Jack

    Hello.
    I can`t delete files which are located in more subdirectories. I have to give it full path and I have a lot of them!
    How can I give it just one path and it`ll search and delete in all sub-directories? I have only an extension type I have to delete. *.bb extension.
    Thanx

    • Hi Jack,
      Do you want to delete all sub directories, or all files with a .bb extension? Basically forfiles can do both, if you tell it to. For example, c:\temp has many subdirectories, and I want to delete all of them:

      forfiles /S /P C:\temp /C "cmd /c if @isdir==TRUE rd /s /q @file"

      To find and delete all files with a .bb extension with forfiles:

      forfiles /S /P C:\temp /M *.bb /C "cmd /c if @isdir==FALSE del @file"

      For testing purposes, you can always start with an echo command:

      forfiles /S /P C:\temp /M *.bb /C "cmd /c if @isdir==FALSE echo del @file"
  4. Is it possible to have the code delete the files older than one day but not older than 15?

    • Hello Aaron, thank you for your comment.

      With ForFiles, you can execute whatever command or script you like, so if you can script it you can execute it with ForFiles. But then I wouldn’t use ForFiles but something like PowerShell to do the job.

      • Sara

        Hi, Jan
        Can I use a variable for the number of days in /D -30 ?
        I’m using FORFILES in a T-SQL stored procedure within a loop where the number of days varies.
        SET @sqlcmd = ‘FORFILES /P “‘+@FileDrive+@OutboundFolder+'” /M *copy.xlsx /C “cmd /c del @path” /D -30’

Comments are closed