27

I need to search a file on my disk modified after a given date using the command line.

For example:

   dir /S /B WHERE modified date > 12/07/2013
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Daniel Peñalba
  • 30,507
  • 32
  • 137
  • 219

7 Answers7

46

The forfiles command works without resorting to PowerShell. The article is here:

Find files based on modified time

Microsoft Technet documentation: forfiles

For the example above:

forfiles /P <dir> /S /D +12/07/2013
  • /P The starting path to search
  • /S Recurse into sub-directories
  • /D Date to search, the "+" means "greater than" or "since"
John Jesus
  • 2,284
  • 16
  • 18
35

You can use PowerShell to do this. Try:

Get-ChildItem -Recurse | Where-Object { $_.LastWriteTime -ge "12/27/2016" }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ralf de Kleine
  • 11,464
  • 5
  • 45
  • 87
5

You can search files modified after a given date using XCOPY as in this example, looking for files since last day of 2018:

xcopy *.* c:\temp\*.* /D:12-31-2018 /L /S

In this example, you are in the directory where your search begins.

C:\temp*.* is only a syntax requisite, and nothing will be copied there.

/D:12-31-2018 specifies the files modified date you are looking for, including the specified date.

/L: Shows the filenames, including drive and path, also makes XCOPY do not copy any file.

/S: Search in subdirectories.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
David Hernán
  • 61
  • 1
  • 3
4

I was after the size of the files changed and did not have PowerShell. I used the following, but the clue came from other posts:

http://www.scotiasystems.com/blog/it-hints-and-tips/quick-way-to-find-recently-changed-files-in-windows and Windows command for file size only

set Target=E:\userdata
rem Date format is M-D-YYYY
set date=12-13-2013
set Filelist=d:\temp\filelist.txt
set Sizelist=d:\temp\sizelist%date%.csv

echo Target is %Target%
echo Start date is %date%
echo file list is %Filelist%
echo Sizelist is %sizelist%

Xcopy %Target% /D:%date% /L /S  > %Filelist%
echo FileSize (bytes), FileName > %sizelist%

For /f "tokens=1 delims=;" %%j in (%Filelist%) do (
                call :Size "%%j"
                )
Goto :EOF

:Size
@echo off
echo %~z1, %1 >> %sizelist%
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • The first link is broken: *"404 Opps! Something went wrong… Page not found. Please continue to our home page"* – Peter Mortensen Sep 14 '19 at 17:06
  • First link archive is at https://web.archive.org/web/20120806221128/http://www.scotiasystems.com/blog/it-hints-and-tips/quick-way-to-find-recently-changed-files-in-windows/ – Ray Woodcock Jul 18 '21 at 06:50
2

I had the same problem, so I created a list using XCOPY and the modified-by date I was looking for, used a for loop to traverse the list, and added the date/time information I needed for each file to a log:

xcopy X:\file_*.log X:\temp /D:07-17-2014 /L /Y > X:\files.txt
for /f "tokens=* delims=" %%a in (X:\files.txt ) do (
    @echo %%~ta %%a >> X:\files.log
)

It resulted in something like the following, which is exactly what I wanted.

X:\>()
07/17/2014 09:41 AM X:\file_201407170600.log

X:\>()
07/17/2014 09:41 AM X:\file_201407170615.log

X:\>()
07/17/2014 09:23 AM X:\file_201407170630.log
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
thehme
  • 2,698
  • 4
  • 33
  • 39
2

If you decide to use PowerShell, this will also work with time and date ranges:

Get-ChildItem -Recurse | Where-Object {($_.LastWriteTime -ge "04/15/2018 20:00:00") -and ($
_.LastWriteTime -lt "04/15/2018 21:00:00")}

To use a programmatic date or a Locale agnostic date time:

Get-ChildItem -Recurse | Where-Object {($_.LastWriteTime -ge (new-object System.DateTime 2018, 1, 10, 12, 30, 00)) -and ($_.LastWriteTime -lt (new-object System.DateTime 2018, 1, 14, 12, 15, 59))}

Where date and time are entered in increasing time specificity order:

Year, Month, Day, Hour, Minute, Second

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
egallardo
  • 1,234
  • 1
  • 15
  • 25
1

I had a similar challenge. I used forfiles, however I noticed that it gave >= rather than just >. The input date was a variable, and so I didn't want to go through a bunch of hoops/loops to calculate date + 1 day (think about logic for last day of month or last day of year).

I created a function that ran forfiles for a particular date. That gives us all files with a modification date that is >= _date_. And for each file I check if the modification date is _date_, and print the output to a file if and only if it is not equal. That means the output file only has entries for files that are > _date_.

I can then check for existence of the output file to determine if any files in the current directory are greater than the input date. Moreover, if I wanted to know which files are newer, I can view the contents of the output file.

Finally, my input was parsed from a file that used a date format of MM/DD/YYYY, meaning it would be 07/01/2019 for July first. However, the date from FORFILES does not use leading zeros so I need to translate by dropping leading zeros.

My first attempt was to use /A thinking it drops the leading zeros. It doesn't it reads the value as octal -- don't repeat the mistake of my first attempt. So I just created a little helper function :getNum that drops leading zeros.

:: ########################################################################
:: :findNewerFiles
::
::     Windowsfile interface will only tell you if a file is
::     greater than OR EQUAL to the current date. Had to figure a way
::     to get just greater than.
::
::     Use 'forfiles' to find all files that are >= the specific date, and for
::     each file if the files date is not equal to the specific date then echo
::     the file information into the new-file-log.
::
::     If the new-file-log exists after we're all done, then it means there is
::     at least one file newer than the specified date.
::
:: PARMS:
::
::     %1 - MONTH
::
::     %2 - DAY
::
::     %3 - YEAR
::
:: ERRORLEVEL:
::     0  if no newer files found
::     !0 if a newer file was found
::
:findNewerFiles
SETLOCAL
    CALL :getNum M "%~1"
    CALL :getNum D "%~2"
    CALL :getNum Y "%~3"


    SET "RETVAL=1"

    %bu.callecho% PUSHD %G[3PROOT_UNC]%

    ECHO Last build date was: %M%/%D%/%Y%
    del "%G[NEW_FILE_LOG]%" >nul 2>&1

    FORFILES /p .\ /S /D +%M%/%D%/%Y% ^
             /c "cmd /c if /I @ISDIR == false if not @fdate==%M%/%D%/%Y% echo @fdate @path>>%G[NEW_FILE_LOG]%"

    IF EXIST "%G[NEW_FILE_LOG]%" (
        SET "RETVAL=0"
        TYPE "%G[NEW_FILE_LOG]%"
    )

    %bu.callecho% POPD
(ENDLOCAL
 EXIT /B %RETVAL%)





:: ########################################################################
:: :getNum
::
::     Remove leading 0 from input number and place results in output variable
::
:: PARMS:
::
::     %1 - OUTPUT VARIABLE
::          Name of the output variable to be populated
::
::     %2 - INPUT VARIABLE
::          The number to have leading zeros trimmed from
::
:: ERRORLEVEL:
::     0  always
::
:getNum
SETLOCAL
    SET "D=%~1"
    SET "M=%~2"

    IF "%M:~0,1%" EQU "0" (
        SET "M=%M:~1%"
    )

(ENDLOCAL
 SET "%D%=%M%"
 EXIT /B 0)
John Rocha
  • 1,656
  • 3
  • 19
  • 30
  • This looks very slick and well thought out. I'm looking forward to giving this a try once I know how to invoke it. – HPWD Sep 15 '20 at 15:25
  • Thanks! I reviewed what I posted, and I see I have some undeclared globals G[XYZ] for path locations. In case you where wondering :). Cheers. – John Rocha Sep 16 '20 at 18:43