9

Quite simply, how would I find out if a specific file in a folder is older than X hours? The file name and location will always be the same.

Thanks

aschipfl
  • 33,626
  • 12
  • 54
  • 99
user270370
  • 151
  • 1
  • 3
  • 8

4 Answers4

14

Following must be considered on comparing file times with batch code:

  1. Date and time format settings
  2. File system of storage media
  3. Time zone, daylight saving time
  4. Automatic adjustment for daylight saving time
  5. Version of Windows

1. Date and time format settings

There are the environment variables DATE and TIME which on access (and not on start of batch execution) return current date and time in a format depending on Windows Language & region settings respectively Windows Region and Language settings. The country defines the date and time format.

It is even possible there to define for example for German short date format with DD.MM.YYYY (day and month with leading zero) and time format with HH:mm:ss (24 hour format with leading zero for hour, minute and second). But this does not mean that value of DATE and TIME are really using this format. For example TIME is in format H:mm:ss,ms when having selected a German country even with HH:mm:ss defined which means no leading zero on hour, but on minute and second, and additionally milliseconds after a comma in time string. The date string can be also with or without weekday depending on region settings.

And there is the pattern %~t to get last modification date and time of a directory or file. Run in a command prompt window call /? and for /? and read all help pages displayed for those two commands for details. The format of the date and time string returned by %~t as well as displayed on output of command DIR depends also on Windows region settings but is usually not equal the format of variables DATE and TIME. The time of last modification time of a file or directory is usually returned without second value in date/time string.

Best is to find out with following batch file best executed before 10:00 AM what are the formats on current machine for current user.

@echo off
echo Current date/time: %DATE% %TIME%
for %%I in ("%~f0") do echo Batch file time:   %%~tI
pause

2. File system of storage media

On Windows file systems two storage formats are used for the file times:

  • On storage media using NTFS the NTFS precision time is used which is a 64-bit number of 100-nanosecond intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC).

  • On storage media using FAT, FAT16, FAT32 or exFAT the file times are stored using DOS Date Time format with two 16-bit values with a resolution of 2 seconds and using current local time.

This means an odd second is not possible for a file on FAT media, but on NTFS media. Copying a file on an NTFS drive with an odd second in last modification time to a FAT32 drive results in having identical files with 1 second difference in last modification time.

The file times on NTFS media are stored in UTC. What is returned by %~t or command DIR as well as what is displayed for example in Windows Explorer depends on

  • current time zone,
  • daylight saving time for this time zone,
  • if current time is within daylight saving period,
  • and if automatic adjustment for daylight saving time is enabled currently.

Changing any of those 4 parameters results in an immediate change of ALL displayed file times of files and directories on NTFS storage media.

File times on FAT media are more or less constant as using local time on creation, modification or last access, but read further for details.


3. Time zone, daylight saving time

As file times on NTFS media are stored in UTC, but displayed in local time, the current time zone and the daylight saving time for this time zone are important for file time comparisons, especially when done for files on NTFS and FAT32 drives.

The time zone and daylight saving time settings could be important depending on version of Windows also for files on a FAT media. Read below for details.


4. Automatic adjustment for daylight saving time

There is the setting for automatic adjustment for daylight saving time which becomes important when being enabled as by default and currently set time zone defines a daylight saving time adjustment.

For example, daylight saving time is active currently in Europe. Disabling this option in clock settings of Windows results in an immediate change of the displayed file times on NTFS media by -1 hour, and also many files on FAT media depending on version of Windows.

This 1 hour time difference caused by the daylight saving time adjustment must be taken into account on comparing file times on NTFS and FAT media.


5. Version of Windows

NTFS is supported by all Windows NT versions. File times behavior is equal for files and directories on all Windows versions supporting NTFS.

But how file times on FAT media are interpreted depends on version of Windows. Prior Windows Vista the file times on FAT media are independent on change of time zone, daylight saving time setting and automatic adjustment of daylight saving time. Last modification date/time of a file is constant on Windows 2000 and Windows XP.

But on Windows Vista and later the displayed file times on FAT media depend on daylight saving time and automatic adjustment for daylight saving time. The time zone does not directly matter. Selecting another time zone as currently used does not change the displayed file times of files on FAT media as it does for files on NTFS media. But if current time is within daylight saving time period of the active time zone and the automatic adjustment for daylight saving time is enabled and the local time of the file or directory is within the daylight saving time period, +1 hour is added by Windows Vista and later. The files last modified on FAT drives within standard time are constant over the year; just the files last modified within DST period are displayed with or without +1 hour depending on current time with enabled automatic DST adjustment.

That different FAT file time management can be extremely confusing when having for example a public share of a folder on a FAT32 drive on a Windows 7 machine and being connected to this public folder with a Windows XP machine. A file last modified on 2015-09-19 17:39:08 stored on FAT32 drive on Windows 7 PC is displayed today by Windows 7 with German time zone with file time 19.09.2015 17:39:08, but in 2 months although not modified with 19.09.2015 16:39:08, and Windows XP displays same file on connected Windows 7 PC today and in future constant with file time 19.09.2015 17:39:08.

Comparing file times of files stored in archives (ZIP, RAR, ...) with files on NTFS or FAT media can be really a nightmare.


6. Comparing file time with current time

For this task comparing last modification time of a file with current time, it should be enough to just take date and time format settings into account.

The batch code below uses code explained in detail in my answer on Batch file to delete files older than N days. This explanation should be read before using the code below.

Depending on date/time format of the variables DATE and TIME and date/time string returned by %~tI for the file on local Windows PC, it might be necessary to make small modifications to code. Appropriate hints are given in the comment lines of batch code.

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Get seconds since 1970-01-01 for current date and time.
rem From date string only the last 10 characters are passed to GetSeconds
rem which results in passing dd/mm/yyyy or dd.mm.yyyy in expected format
rem to this subroutine independent on date string of environment variable
rem DATE is with or without abbreviated weekday at beginning.
call :GetSeconds "%DATE:~-10% %TIME%"

rem Subtract seconds for 4 hours (4 * 3600 seconds) from seconds value.
set /A "CompareTime=Seconds-4*3600"

rem Define batch file itself as the file to compare time by default.
set "FileToCompareTime=%~f0"

rem If batch file is started with a parameter and the parameter
rem specifies an existing file (or directory), compare with last
rem modification date of this file.
if not "%~1" == "" if exist "%~1" set "FileToCompareTime=%~1"

rem Get seconds value for the specified file.
for %%F in ("%FileToCompareTime%") do call :GetSeconds "%%~tF:0"

rem Compare the two seconds values.
if %Seconds% LSS %CompareTime% (
    echo File %FileToCompareTime% was last modified for more than 4 hours.
) else (
    echo File %FileToCompareTime% was last modified within the last 4 hours.
)
endlocal
goto :EOF


rem No validation is made for best performance. So make sure that date
rem and hour in string is in a format supported by the code below like
rem MM/DD/YYYY hh:mm:ss or M/D/YYYY h:m:s for English US date/time.

:GetSeconds
rem If there is " AM" or " PM" in time string because of using 12 hour
rem time format, remove those 2 strings and in case of " PM" remember
rem that 12 hours must be added to the hour depending on hour value.
set "DateTime=%~1"
set "Add12Hours=0"
if not "%DateTime: AM=%" == "%DateTime%" (
    set "DateTime=%DateTime: AM=%"
) else if not "%DateTime: PM=%" == "%DateTime%" (
    set "DateTime=%DateTime: PM=%"
    set "Add12Hours=1"
)

rem Get year, month, day, hour, minute and second from first parameter.
for /F "tokens=1-6 delims=,-./: " %%A in ("%DateTime%") do (
    rem For English US date MM/DD/YYYY or M/D/YYYY
    set "Day=%%B" & set "Month=%%A" & set "Year=%%C"
    rem For German date DD.MM.YYYY or English UK date DD/MM/YYYY
    rem set "Day=%%A" & set "Month=%%B" & set "Year=%%C"
    set "Hour=%%D" & set "Minute=%%E" & set "Second=%%F"
)

rem Remove leading zeros from the date/time values or calculation could be wrong.
if "%Month:~0,1%"  == "0" if not "%Month:~1%"  == "" set "Month=%Month:~1%"
if "%Day:~0,1%"    == "0" if not "%Day:~1%"    == "" set "Day=%Day:~1%"
if "%Hour:~0,1%"   == "0" if not "%Hour:~1%"   == "" set "Hour=%Hour:~1%"
if "%Minute:~0,1%" == "0" if not "%Minute:~1%" == "" set "Minute=%Minute:~1%"
if "%Second:~0,1%" == "0" if not "%Second:~1%" == "" set "Second=%Second:~1%"

rem Add 12 hours for time range 01:00:00 PM to 11:59:59 PM,
rem but keep the hour as is for 12:00:00 PM to 12:59:59 PM.
if %Add12Hours% == 1 if %Hour% LSS 12 set /A Hour+=12

set "DateTime="
set "Add12Hours="

rem Must use two arrays as more than 31 tokens are not supported
rem by command line interpreter cmd.exe respectively command FOR.
set /A "Index1=Year-1979"
set /A "Index2=Index1-30"

if %Index1% LEQ 30 (
    rem Get number of days to year for the years 1980 to 2009.
    for /F "tokens=%Index1% delims= " %%Y in ("3652 4018 4383 4748 5113 5479 5844 6209 6574 6940 7305 7670 8035 8401 8766 9131 9496 9862 10227 10592 10957 11323 11688 12053 12418 12784 13149 13514 13879 14245") do set "Days=%%Y"
    for /F "tokens=%Index1% delims= " %%L in ("Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N") do set "LeapYear=%%L"
) else (
    rem Get number of days to year for the years 2010 to 2038.
    for /F "tokens=%Index2% delims= " %%Y in ("14610 14975 15340 15706 16071 16436 16801 17167 17532 17897 18262 18628 18993 19358 19723 20089 20454 20819 21184 21550 21915 22280 22645 23011 23376 23741 24106 24472 24837") do set "Days=%%Y"
    for /F "tokens=%Index2% delims= " %%L in ("N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N") do set "LeapYear=%%L"
)

rem Add the days to month in year.
if "%LeapYear%" == "N" (
    for /F "tokens=%Month% delims= " %%M in ("0 31 59 90 120 151 181 212 243 273 304 334") do set /A "Days+=%%M"
) else (
    for /F "tokens=%Month% delims= " %%M in ("0 31 60 91 121 152 182 213 244 274 305 335") do set /A "Days+=%%M"
)

rem Add the complete days in month of year.
set /A "Days+=Day-1"

rem Calculate the seconds which is easy now.
set /A "Seconds=Days*86400+Hour*3600+Minute*60+Second"

rem Exit this subroutine.
goto :EOF

rojo added information on how date and time format settings, file system and Windows version can be ignored by using wmic - the Windows Management Instrumentation command-line utility.

Using wmic has the advantage of fixed format for the date/time strings and therefore the batch code works on all Windows computers without adaptations to local date/time format.

Also version of Windows does not matter on using wmic because of internal usage of GetFileTime function (most likely).

The file system becomes only important on also evaluating minutes offset of local time / file time to UTC. Command wmic returns on FAT drives just +*** for the minutes offset to UTC while the minutes offset is correct for the last modification file time of a file on an NTFS drive.

Example for same file on NTFS and FAT32 drive:

NTFS:  20071011192622.000000+120
FAT32: 20071011192622.000000+***

+120 is sum of +60 minutes for CET (Central European Time) and +60 minutes for active daylight saving time, or in other words +120 minutes for CEST (Central European Summer Time).

The batch code below does not evaluate therefore the minutes offset to UTC which is not needed on comparing last modification file time of a file with current local time.

Further the file name must be specified always with full path in wmic command line. Just specifying the file name for a file in current directory or a file name with relative path does not work. And each backslash must be escaped with one more backslash in file name with path.

The main disadvantage on using wmic is the speed. The batch code above needs on my computer with Windows XP about 50 ms to finish according to Process Monitor log (average of several runs). The batch code below calling wmic twice needs for the same task about 1500 ms to finish on Windows XP (also an average value). The usage of wmic on a large number of files is definitely no good idea for that reason at least on Windows XP if it can be avoided because local date/time format is known.

Another disadvantage of the wmic solution is the missing availability of wmic.exe on Windows 11 build 22572 and newer versions of Windows which were installed completely new and not upgrades from former Windows versions. Please read the Microsoft documentation page Deprecated features for Windows client with the information:

Windows Management Instrumentation Command line (WMIC) tool
The WMIC tool is deprecated in Windows 10, version 21H1 and the 21H1 General Availability Channel release of Windows Server. This tool is superseded by Windows PowerShell for WMI. Note: This deprecation only applies to the command-line management tool. WMI itself isn't affected.

There can be installed wmic.exe via Settings > Apps > Optional features listing WMIC for installation on Windows 10/11 on missing in the directory %SystemRoot%\System32\wbem.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
if exist %SystemRoot%\System32\wbem\wmic.exe goto GetCurrent

echo ERROR: The WMI command-line utility wmic.exe is not installed.
echo(
echo There should not be used anymore batch files with WMIC on this computer.
echo(
echo There could be installed WMIC via Settings ^> Apps ^> Optional features.
echo(
pause
exit /B

:GetCurrent
rem Get seconds since 1970-01-01 for current date and time.
for /F "tokens=2 delims==." %%T in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do call :GetSeconds %%T

rem Subtract seconds for 4 hours (4 * 3600 seconds) from seconds value.
set /A "CompareTime=Seconds-4*3600"

rem Define batch file itself as the file to compare time by default.
set "FileToCompareTime=%~f0"

rem If batch file is started with a parameter and the parameter
rem specifies an existing file (or directory), compare with last
rem modification date of this file.
if not "%~1" == "" if exist "%~f1" set "FileToCompareTime=%~f1"

rem Get seconds value for the specified file.
set "DataFile=%FileToCompareTime:\=\\%"
for /F "usebackq tokens=2 delims==." %%T in (`%SystemRoot%\System32\wbem\wmic.exe DATAFILE where "name='%DataFile%'" GET LastModified /VALUE`) do call :GetSeconds %%T

rem Compare the two seconds values.
if %Seconds% LSS %CompareTime% (
    echo File %FileToCompareTime% was last modified for more than 4 hours.
) else (
    echo File %FileToCompareTime% was last modified within the last 4 hours.
)
endlocal
goto :EOF


rem Date/time format used by the command line utility of Windows
rem Management Instrumentation is always YYYYMMDDHHmmss with a
rem dot and a 6 digit microsecond value and plus/minus 3 digit
rem time offset to UTC in minutes independent on region and
rem language settings. Microsecond is always 000000 for a file
rem time. The minutes offset including time zone offset and
rem current daylight saving time offset is returned for a file
rem time only for a file on an NTFS drive. Minutes offset is
rem +*** for a file on a FAT drive (at least on Windows XP).

:GetSeconds
rem Get year, month, day, hour, minute and second from first parameter.
set "DateTime=%~1"
set "Year=%DateTime:~0,4%"
set "Month=%DateTime:~4,2%"
set "Day=%DateTime:~6,2%"
set "Hour=%DateTime:~8,2%"
set "Minute=%DateTime:~10,2%"
set "Second=%DateTime:~12,2%"
rem echo Date/time is: %Year%-%Month%-%Day% %Hour%:%Minute%:%Second%

rem Remove leading zeros from the date/time values or calculation could be wrong.
if %Month:~0,1%  == 0 set "Month=%Month:~1%"
if %Day:~0,1%    == 0 set "Day=%Day:~1%"
if %Hour:~0,1%   == 0 set "Hour=%Hour:~1%"
if %Minute:~0,1% == 0 set "Minute=%Minute:~1%"
if %Second:~0,1% == 0 set "Second=%Second:~1%"

rem Must use two arrays as more than 31 tokens are not supported
rem by command line interpreter cmd.exe respectively command FOR.
set /A "Index1=Year-1979"
set /A "Index2=Index1-30"

if %Index1% LEQ 30 (
    rem Get number of days to year for the years 1980 to 2009.
    for /F "tokens=%Index1% delims= " %%Y in ("3652 4018 4383 4748 5113 5479 5844 6209 6574 6940 7305 7670 8035 8401 8766 9131 9496 9862 10227 10592 10957 11323 11688 12053 12418 12784 13149 13514 13879 14245") do set "Days=%%Y"
    for /F "tokens=%Index1% delims= " %%L in ("Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N") do set "LeapYear=%%L"
) else (
    rem Get number of days to year for the years 2010 to 2038.
    for /F "tokens=%Index2% delims= " %%Y in ("14610 14975 15340 15706 16071 16436 16801 17167 17532 17897 18262 18628 18993 19358 19723 20089 20454 20819 21184 21550 21915 22280 22645 23011 23376 23741 24106 24472 24837") do set "Days=%%Y"
    for /F "tokens=%Index2% delims= " %%L in ("N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N") do set "LeapYear=%%L"
)

rem Add the days to month in year.
if "%LeapYear%" == "N" (
    for /F "tokens=%Month% delims= " %%M in ("0 31 59 90 120 151 181 212 243 273 304 334") do set /A "Days+=%%M"
) else (
    for /F "tokens=%Month% delims= " %%M in ("0 31 60 91 121 152 182 213 244 274 305 335") do set /A "Days+=%%M"
)

rem Add the complete days in month of year.
set /A "Days+=Day-1"

rem Calculate the seconds which is easy now.
set /A "Seconds=Days*86400+Hour*3600+Minute*60+Second"

rem Exit this subroutine.
goto :EOF
Mofi
  • 46,139
  • 17
  • 80
  • 143
  • 3
    You get a +1 from me because that's an impressive essay and explanation. Just a quick note, though. Nos. 1, 2, and 5 can be negated by using WMI queries, which are locale and file system agnostic. `wmic os get localdatetime` for the current date and time; and `wmic datafile where "name='c:\\path\\to\\file.ext'" get lastmodified` for the last modified time in the same format. Both results are in GMT and report the time zone / DST offset at the end of the value. – rojo Sep 19 '15 at 20:45
  • Thanks @rojo for this additional information. I have added one more code example using __wmic__ with some information about advantages and disadvantages on using __wmic__. – Mofi Sep 20 '15 at 15:09
  • I must also say that your answer impressed me. For this reason I had to once again open a bounty but this time for you. Even if it turns out that the bounty is incremented in multiples of 2, this is merited. – Paul Sep 21 '15 at 09:39
  • Many thanks @Paul. I thought, that it was really time to write all of what I know about file time management by Windows and comparison of file times after reading many "older than" questions on StackOverflow. I hope that this large answer helps many others. Additional input regarding file times is welcome at any time. – Mofi Sep 22 '15 at 05:52
  • 2
    Unfortunately, there is another issue with the `wmic` approach: you cannot specify file paths containing both `,` and `)` -- see also my question: [How to escape both comma and closing parenthesis in WHERE clause of WMIC?](https://stackoverflow.com/q/37198153) – aschipfl Jul 27 '17 at 08:00
4

Alternatively you could create a simple program using C# for example like that:

// compile using c:\Windows\Microsoft.NET\Framework\v3.5\csc FileByAge.cs
using System;
using System.IO;

public static class Program
{
  public static void Main(string[] args)
  {
    double age = double.Parse(args[0]);
    string fileName;
    while ((fileName = Console.ReadLine()) != null)
    {
      if(age >= (DateTime.Now - new FileInfo(fileName).CreationTime).TotalHours)
      {
        continue;
      }
      Console.WriteLine(fileName);    
    }
  }
}

That program could then be used to find all files that are older than 2 hours within a batch file like that:

for /F "delims=" %f in ('dir /B *.txt^|FileByAge.exe 2') do echo %f

An improved and self-compiling version

As mentioned by @Paul one could even build a hacky hybrid batch / c# file that will compile and run itself:

@echo off
setlocal
set CsFile=%TEMP%\%~n0.cs
set ExeFile=%TEMP%\%~n0.exe
pushd %SystemRoot%\Microsoft.NET\Framework
for /F %%f in ('dir /B /O:-N v*') do cd %%f & goto :BreakLoop;  
:BreakLoop
(echo /* & type "%~f0") > "%CsFile%"
csc.exe /nologo /out:"%ExeFile%" "%CsFile%" 
del "%CsFile%"
popd
more | "%ExeFile%" %*
del "%ExeFile%"
endlocal
goto:eof
*/

using System;
using System.IO;

public static class Program
{
    public static void Main(string[] args)
    {
        var olderThen = args[0].Contains("older");
        var targetAge = double.Parse(args[1]);
        string fileName;
        while ((fileName = Console.ReadLine()) != null)
        {
            if (string.Empty == fileName)
            {
                continue;
            }
            var fileAge = (DateTime.Now - new FileInfo(fileName).CreationTime).TotalHours;
            if (olderThen ? targetAge > fileAge : targetAge < fileAge)
            {
                continue;
            }
            Console.WriteLine(fileName);
        }
    }
}

And can be used like this:

for /F "delims=" %f in ('dir /B *.txt^|FileByAge.bat older 2') do echo %f
Martin
  • 10,738
  • 14
  • 59
  • 67
  • @iKiWiXz Yes, it is a C# program that you can compile and use within your batch file on almost any Windows PC. You could even integrate everything within in your batch file if you like. It's a bit nitpicky to down vote a valid solution that maybe did not help the OP but works and might help others. – Martin Feb 12 '15 at 17:13
  • 1
    Hi @Martin +1 btw. May the script can compile the source on the fly. I already saw a hybrid script that do this. I will look at it. thanks – Paul Sep 17 '15 at 05:00
  • @Martin I just tried, it works well except for files containing spaces. – Paul Sep 17 '15 at 23:46
  • 1
    @Paul the issue with spaces is coming from the `for` command. Just add a `"delims="` to fix it. I also added a self-compiling version of the script as you suggested. – Martin Sep 18 '15 at 13:48
  • @Martin Shame on me for the `"delims="` :D By hybrid I was thinking of this https://gist.github.com/anonymous/2061842e1c56b77c8a74 but your is just fine :) Do you think it's possible to rewrite without much work `>=` as argument like for: `dir /B *.txt^|FileByAge.bat ^>=2` – Paul Sep 18 '15 at 20:01
  • 1
    @Paul I added one argument to specify the comparison operator – Martin Sep 21 '15 at 08:44
  • @Martin Great! If I understand the code here, if I leave aside "older", it means it will process the contrary and look for the newest files than n? – Paul Sep 21 '15 at 08:54
  • 1
    @Paul Yes, just pass something that does not contain the word `older` – e. g. `younger` – Martin Sep 21 '15 at 08:58
  • @Martin, I must explain one thing. I wanted to give you a bounty (something I did), but I did not know I had to wait 24 hours. So during this time Mofi came and gave themselves a lot of trouble to respond. So I wanted to give a second bounty but this time for him. The problem is that it is incremented. I wanted it to be an equal share because it is merited. I hope you will forgive me if I attribute to Mofi. – Paul Sep 21 '15 at 09:17
  • @Paul No problem here. Helping someone out is way more important to me than some stupid reputation points :D – Martin Sep 22 '15 at 18:32
2

Pure batch is horrible at date math. What happens if your script runs shortly after midnight? What if the time check spans a Daylight Savings Time change?

I propose invoking Windows Script Host and borrowing from a language that better handles date / time math. Here's a hybrid batch / JScript script that'll compute the age of a file or directory pretty easily. Save it with a .bat extension and give it a shot.

@if (@CodeSection==@Batch) @then

@echo off
setlocal

set "file=C:\Path\To\File.ext"

for /f %%I in ('cscript /nologo /e:JScript "%~f0" "%file%"') do (
    rem // value contained in %%I is in minutes.

    if %%I gtr 240 (

        echo %file% is over 4 hours old.

        rem // do stuff here to take whatever actions you wish
        rem // if the file is over 4 hours old.
    )
)

goto :EOF

@end // end batch portion / begin JScript hybrid chimera

var fso = new ActiveXObject("scripting.filesystemobject"),
    arg = WSH.Arguments(0),
    file = fso.FileExists(arg) ? fso.GetFile(arg) : fso.GetFolder(arg);

// Use either DateCreated, DateLastAccessed, or DateLastModified.
// See http://msdn.microsoft.com/en-us/library/1ft05taf%28v=vs.84%29.aspx
// for more info.

var age = new Date() - file.DateLastModified;
WSH.Echo(Math.floor(age / 1000 / 60));

For more information on batch / JScript hybrid scripts, see this GitHub page. The style used above is similar to Hybrid.bat on that page. This answer is based on another. For what it's worth, PowerShell is also good at handling date math; but WSH executes much more quickly.

Community
  • 1
  • 1
rojo
  • 24,000
  • 5
  • 55
  • 101
2

The solution to this will depend much on the expected time-range, since AFAIK you don't get time as one integer in a batch file without external programs. This means you have to parse the time value in your script, and the amount of parsing and the number of calculations needed, depend on the range you require it to work for. Here is one simple solution. It assumes that the file can NOT be older than 24hours.

set "filename=myfile.txt"
rem extract current date and time
for /f "tokens=1-5 delims=.:, " %%a in ("%date% %time%") do (
  set day=%%a&set mon=%%b&set yr=%%c&set hr=%%d&set min=%%e
)
rem extract file date and time
for /f "tokens=1-5 delims=.:, " %%a in ('"dir %filename%|find "%filename%""') do (
  set fday=%%a&set fmon=%%b&set fyr=%%c&set fhr=%%d&set fmin=%%e
)
rem calculate age of file (in minutes)
set /a "age=((hr*60+min)-(fhr*60+fmin)+(24*60))%%(24*60)"
set /a "max=4*60"
if %age% geq %max% echo.file is older than 4 hours
Superole
  • 1,329
  • 21
  • 29
  • Some extra information of readers of this simple solution for files last modified on same day on running this batch file: __1.__ The file name assigned to the environment variable `filename` cannot contain a space or one of these characters ``&()[]{}^=;!'+,`~``. __2.__ `set day=%%a&set mon=%%b&set yr=%%c&` and `set fday=%%a&set fmon=%%b&set fyr=%%c&` can be removed from the code as only the hour and minute environment variables are used to calculate the time difference. __3.__ The code does not work correct if an hour or a minute is `08` or `09` which are invalid octal numbers handled as `0`. – Mofi Apr 21 '23 at 06:08