Check if file was modified after xx days in the past
Asked Answered
J

4

4

I am checking for the date modified in a file. I would like to test whether the file was modified after the /d -3. According to the docs, this will check if the file was modified before that date. I need to check if the file was modified after that date. The docs also state that I can specify a date. I might end up doing it this way though it would be a little more complicated to generate a date to check against which I would prefer to avoid if possible. How might I go about this?

forfiles /m Item_Lookup2.csv /d -3 >nul 2>nul && (
  echo - updated

  goto :PROCESS_FILE
) || (

  echo - out of date
  set outdated="true"

  goto :CHECK_ERRORS
)

I found this in this answer

Janitress answered 3/6, 2015 at 12:37 Comment(3)
Read the documentation again, specifically the /D date section.Tericaterina
@Tericaterina I need it to be a numeric value, not a specific date. I was hoping for an easier method.Janitress
Possible duplicate of FORFILES date -after- (date calc in cmd file)Monolayer
C
4

You're on the right track, but forfiles /d -n tests for files modified n days or earlier, not later. What you need to do is reverse your && and || code blocks, and maybe specify 4 days instead of 3.

If match, then it's 4 days old or older, and classified as out of date. If no match, it's been updated in the past 3 days.

Try this:

forfiles /d -4 /m "Item_Lookup2.csv" >NUL 2>NUL && (
    echo - out of date
    set outdated="true"
    goto :CHECK_ERRORS
) || (
    echo - updated
    goto :PROCESS_FILE
)

Bonus tip: If you'd like to do some testing, you can manipulate the last modified timestamp of a file manually using a PowerShell command:

powershell "(gi Item_Lookup2.csv).LastWriteTime='6/1/2015 09:30:00 AM'"

... will set the last modified timestamp of Item_Lookup2.csv to June 1 at 9:30 AM. Salt to taste.

Close answered 3/6, 2015 at 13:26 Comment(3)
Wow - such a simple and obvious solution, once I see it. But I'll bet I'm one of many who would have never thought of this solution.Grog
Thanks! Of course if the file doesn't exist at all, it'll result in a false positive. An additional if not exist "Item_Lookup2.csv" check ought to be added before the forfiles line to prevent that.Close
Check out my ROBOCOPY solution - just as effective, but slightly different rules for computing age. Neither solution is better, it just depends on what rules you want to use.Grog
G
2

I really like rojo's answer - so simple. I find it interesting that it ignores the time component when computing the age. So an actual age of 1 second could be computed as one day if the current time is midnight and the last modified time stamp is 23:59:59 from the day before. This may or may not be the behavior you want.

I have a different solution based on ROBOCOPY that uses the full time stamp when computing the file age. So if you specify a max age of 3 days, then it looks for files that have been created or modified within the last 72 hours.

One nice thing about ROBOCOPY is it allows you to specify the minimum age, and/or the maximum age.

The returned ERRORLEVEL is complicated, making it inconvenient to interpret. Instead of using the ERRORLEVEL, I check to see if the command listed the file in question. I use a FOR /F loop that raises an error if no file is listed. The BREAK command is simply a command that always succeeds and produces no output if a file was listed.

There are lots of ROBOCOPY options, many of which are needed for this application :-)

(for /f %%A in (
  'robocopy . "%temp%" "Item_Lookup2.csv" /maxage:3 /is /it /xx /l /ndl /njh /njs'
) do break) && (
  echo - updated
  goto :PROCESS_FILE
) || (
  echo - out of date
  set outdated="true"
  goto :CHECK_ERRORS
)
Grog answered 4/6, 2015 at 4:29 Comment(3)
Interesting idea! I will have to try this out tomorrow when I'm on Windows. What should I expect in %%A?Janitress
It lists the ROBOCOPY class (new or same for example), the file size, and the file name (with path). You can add the /NC and /NS options to eliminate the class and size from the output.Grog
@Janitress - You can also add the /TS option to get the last modified timestamp. I believe the format will always be YYYY/MM/SS hh:mm:ss in 24 hour format, regardless of locale.Grog
M
1

Filtering files by different times is not so easy with pure batch so I've tried to create a tool for common usage - FileTimeFilterJS.bat (probably far from perfect) .Try with:

call FileTimeFilterJS.bat "." -filetime modified -direction after -dd -3
Murial answered 3/6, 2015 at 12:52 Comment(5)
Looks like to use this I should have the library saved in `E:\JScript\'?Janitress
@Janitress - NO! it uses built-in wsh/jscript. `E:\JScript\' is just a command line argument to cscript.exe and means use jscript engine.Murial
Any way to specify a single file? Or how should I act on the output?Janitress
@Janitress - no - as it is implemented you can only pass a directory to search.You can filter the output with FINDSTR or FINDMurial
I really like this idea, though its not the simplest answer that I was looking for. Thanks for sharing, I'll very likely use this more in the future as I had no idea you could execute JS ( or otherwise ) as/from a batch file.Janitress
U
0

forfiles /D +n apparently looks for files with timestamps in the future. Alternatively, use this Powershell script to start with:

## usage: ff.ps1 [-age n] [-mask *.*]
## find files newer than n days 
## with filenames matching mask

Param (
    [float]$age = 0,
    [string]$mask = '*.*'
)

$from = $(get-date).addDays(-$age)
GCI -path '.' -filter $mask -recurse -force | Where {$_.attributes -ne "Directory"-and $_.lastwritetime -gt $from } | ForEach { write-host $_.lastwritetime '   ' $_.fullname }

It's pretty simple, you can specify the maximum age (-age n) and/or the filemask (-mask *.csv). Output is timestamp + full filename which can easily be modified. Look at the date calculation and compare it to the nightmare needed with DOS batch.

Undetermined answered 3/6, 2015 at 14:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.