Select a file (or set of files) and execute a command on each file. Batch processing.

      FORFILES [/p Path] [/m SrchMask] [/s] [/c Command] [/d [+ | -] {date | dd}]   

   /p Path      The Path to search  (default=current folder)

   /m SrchMask  Select files matching the specified search mask
                Wildcards are literal (non standard):
                A mask of -m *   will iterate all files (this is the default)
                A mask of -m *.* will skip any extensionless filename.

   /s           Recurse into sub-folders

   /C command   The command to execute for each file.
                Wrap the command string in double quotes.
                Default = "cmd /c echo @file"

                The Command variables listed below can also be used in the
                command string.

   /D date      Select files with a last modified date greater than or 
                equal to (+), or less than or equal to (-),
                the specified date, using the region specific date format.
                The /? Help text will display the date format for your region
                typically "MM/DD/yyyy" or "DD/MM/yyyy".

   /D +dd       Select files with a last modified date greater than or
                equal to the current date plus "dd" days. (in the future)

   /D -dd       Select files with a last modified date less than or
                equal to the current date minus "dd" days. (in the past)

                A valid "dd" number of days can be any number in
                the range of 0 to 32768.   (89 years)

                "+" is taken as the default sign if not specified.

   Command Variables:
      @file    The name of the file.
      @fname   The file name without extension.                
      @ext     Only the extension of the file.                  
      @path    Full path of the file.
      @relpath Relative path of the file.          
      @isdir   Returns "TRUE" if a file type is a directory,
               and "FALSE" for files.
      @fsize   Size of the file in bytes.
      @fdate   Last modified date of the file.
      @ftime   Last modified time of the file.

To include special characters in the command line, use the hexadecimal code for the character in 0xHH format (ex. 0x09 for tab). Internal CMD.exe commands should be preceded with "cmd /c".

Last modified time is taken to be midnight 00:00, so FORFILES /D +TodaysDate will find files created today.

Last modified dates set in the future are not common but can happen when your computer clock date/time is changed e.g. due to daylight savings time.

Early versions of FORFILES were supplied in the NT resource kit and used unix style '-' parameters, (still supported for backwards compatibility) also the /D option accepted dates only in DDMMYYYYHHMN format.


Recent versions of FORFILES contain a bug, in processing command line arguments: running a /c command that contains an argument such as FORFILES /C "PING -a" will fail. The expected convention is that argv[0] will contain the program name, but FORFILES instead passes the first argument as argv[0]. Old versions e.g. FORFILES version 1.46 (24th March 2006) do not suffer from this bug.

One workaround for this is to include the program name as the first argument, this will be passed along by FORFILES and the CreateProcess call will then work as expected:
FORFILES /c "Ping Ping -a"

Alternatively pass the command to CMD /C, which will then process all the arguments correctly.
If you want to use an internal commmand, or if you want to use redirection, pipe, command concatenation, etc, then you must use CMD /C.
FORFILES /c "CMD /C Ping -a"

There are some disadvantages to using CMD.exe with FORFILES, a new process will be created and destroyed for every file that FORFILES processes, so if you loop through 1000 files, then 1000 copies of CMD.exe will be opened and closed, this will affect performance. Also any variable created with SET will be lost as soon as FORFILES moves on to the next file.

In most cases using a simple FOR command along with Parameter extensions will provide a better/less buggy solution.

Return values

If ForFiles finds one or more matches if will return Errorlevel =0
If ForFiles finds no matches if will return Errorlevel =1 and will print "ERROR: No files found with the specified search criteria."


Delete the testfile if it is is 5 days old or older:

C:\> forfiles /m testfile.txt /c "cmd /c Del testfile.txt " /d -5

Find all .xlsx files that were last modified 30 days ago or older:

C:\> FORFILES /M *.xlsx /C "cmd /c echo @path was changed 30 days ago" /D -30

List the size of all .doc files:

C:\> FORFILES /S /M *.doc /C "cmd /c echo @fsize"

Run a command against each text file newer than 1st Jan 2021:

C:\> FORFILES /D +01/01/2021 /m *.txt /C "CMD /c echo @fname is new since Jan 1st 2021"

Rule #1: Don’t sweat the small stuff.
Rule #2: It's all small stuff - Dr Robert S Eliot, University of Nebraska cardiologist

Related commands

Syntax - Delete files older than N days
OldNewThing - Combining ForFiles and FOR.
Parameter extensions - Get file size(s).
FOR - Conditionally perform a command several times.
Equivalent PowerShell: ForEach-Object - Loop for each object in the pipeline.
Equivalent bash command (Linux): find - Search for files that meet a desired criteria.

Copyright © 1999-2024
Some rights reserved