检查文件是否早于 2 分钟

Check if file is older than 2 minutes

我想检查文件 "test.txt" 是否超过两分钟。

到目前为止,我可以检查机器的当前时间戳和文件的最后修改日期。

但是如何从当前机器时间中减去 now 来检查文件是否早于两分钟?

set mytimestamp="%date:~0,2%.%date:~3,2%.%date:~6,4% 

%time:~0,2%:%time:~3,2%"

echo %mytimestamp%

SET filename="test.txt"
FOR %%f IN (%filename%) DO SET filedatetime="%%~tf"
::echo %filedatetime%


IF %filedatetime% == %mytimestamp% goto same

goto notsame


:same
ECHO "files same"
goto :eof

:notsame 
ECHO "files not same"
goto :eof


:eof

通常完成此操作的方法是将两个时间转换为时间坐标,(将时间表示为多个时间单位的常规数值,比如分钟,因为过去的固定时间点,已知as "epoch",) 从第二个时间坐标中减去所需的偏移量(在您的情况下为 2 分钟),然后将两个时间坐标作为数字进行比较。

不幸的是,获取 windows 日期和时间命令给出的文本(人类可读)时间戳并将其转换为时间坐标非常困难。即使你费尽心机地提取年号、月号、月中的日期、小时和分钟,并将所有这些连接成看起来像数字的东西,你仍然无法处理它就像一个数字,因为例如从 201504170001 中减去 2 得到 201504169999,而不是 201504162359.

因此,为了使其正常工作,您必须使用数字乘法和加法而不是字符串连接,这意味着您必须将年数乘以一年中的分钟数,然后加上它月份数乘以一个月中的分钟数,然后加上月份中的第几天乘以一天中的分钟数,依此类推,但为了做到这一点,您首先需要知道每个月是 30 天还是 31 天,而且由于二月可能有 28 天或 29 天,这取决于它是否是闰年,这变得更加复杂。

所以,我会说,算了吧。在 windows 批处理文件中这样做是不合理的。改用真正的编程语言编写一个小程序,或者找到一种方法来完成您正在尝试做的事情,而不必检查文件的时间戳是否早于某个时间量。

这应该有效:

set hh=%TIME:~0,2%
set mm=%TIME:~3,2%
set ss=%TIME:~6,2%

set /a sum_sec=%hh% * 3600 + %mm% * 60 + %ss% -120

set /a h=%sum_sec% / 3600
set /a m=(%sum_sec%/60) - 60 * %h%
set /a s=%sum_sec% - 60 * (%sum_sec%/60)
IF %h% LSS 10 set h=0%h%
IF %m% LSS 10 set m=0%m%
IF %s% LSS 10 set s=0%s%

set new_time=%h%:%m%:%s%

forfiles /P "C:\SomePath" /S /M test.txt /C "cmd /c if @ftime LSS %new_time% del /F /Q @path"

在此示例中,如果文件 test.txt 超过 2 分钟,我们将删除它。您可以通过将 120 替换为任何其他值(以秒为单位)来改变行 set /a sum_sec=%hh% * 3600 + %mm% * 60 + %ss% -120 中的时间。

像往常一样,我做事过火了。

dt2epoch.bat -- 本地 date/time 到 Unix 纪元(自 1970-01-01 00:00:00 UTC 以来的秒数)

@echo off
setlocal enabledelayedexpansion

if "%~1" equ "" (echo.dt2epoch.bat: usage: missing {year}.& exit /b 1)
if "%~2" equ "" (echo.dt2epoch.bat: usage: missing {month}.& exit /b 1)
if "%~3" equ "" (echo.dt2epoch.bat: usage: missing {day}.& exit /b 1)
if "%~4" equ "" (echo.dt2epoch.bat: usage: missing {hour}.& exit /b 1)
if "%~5" equ "" (echo.dt2epoch.bat: usage: missing {minute}.& exit /b 1)
if "%~6" equ "" (echo.dt2epoch.bat: usage: missing {second}.& exit /b 1)
if "%~7" neq "" (echo.dt2epoch.bat: usage: too many arguments.& exit /b 1)

set year=%~1
set month=%~2
set day=%~3
set hour=%~4
set minute=%~5
set second=%~6

rem remove leading zeroes, which set /a stupidly takes as octal (see <
for /f "tokens=* delims=0" %%i in ("!year!") do set year=%%i
for /f "tokens=* delims=0" %%i in ("!month!") do set month=%%i
for /f "tokens=* delims=0" %%i in ("!day!") do set day=%%i
for /f "tokens=* delims=0" %%i in ("!hour!") do set hour=%%i
for /f "tokens=* delims=0" %%i in ("!minute!") do set minute=%%i
for /f "tokens=* delims=0" %%i in ("!second!") do set second=%%i
rem echo.!year!-!month!-!day! !hour!:!minute!:!second!

rem get the (negative of the) local time zone offset
set i=0
for /f "delims=" %%i in ('w32tm /tz') do (
    set line[!i!]=%%i
    set /a i+=1
)
set /a ntzo=!line[0]:~-28,-24!
if "!line[0]:~0,40!" equ "Time zone: Current:TIME_ZONE_ID_DAYLIGHT" set /a ntzo+=!line[2]:~-28,-25!
rem echo.ntzo=!ntzo!

rem month days and cumulative past month days lookup
set MDAYS[1]=31
set MDAYS[2]=28
set MDAYS[3]=31
set MDAYS[4]=30
set MDAYS[5]=31
set MDAYS[6]=30
set MDAYS[7]=31
set MDAYS[8]=31
set MDAYS[9]=30
set MDAYS[10]=31
set MDAYS[11]=30
set MDAYS[12]=31
set CPMDAYS[1]=0
set /a CPMDAYS[2]=MDAYS[1]
set /a CPMDAYS[3]=CPMDAYS[2]+MDAYS[2]
set /a CPMDAYS[4]=CPMDAYS[3]+MDAYS[3]
set /a CPMDAYS[5]=CPMDAYS[4]+MDAYS[4]
set /a CPMDAYS[6]=CPMDAYS[5]+MDAYS[5]
set /a CPMDAYS[7]=CPMDAYS[6]+MDAYS[6]
set /a CPMDAYS[8]=CPMDAYS[7]+MDAYS[7]
set /a CPMDAYS[9]=CPMDAYS[8]+MDAYS[8]
set /a CPMDAYS[10]=CPMDAYS[9]+MDAYS[9]
set /a CPMDAYS[11]=CPMDAYS[10]+MDAYS[10]
set /a CPMDAYS[12]=CPMDAYS[11]+MDAYS[11]

set /a pastLeapDays=(year-1968)/4-(year-1900)/100+(year-1600)/400
if "!month!" equ "0" (set leap=0) else if "!month!" equ "1" (set leap=0) else if "!month!" equ "2" (set leap=0) else (set /a leap="!(year%4)-!(year%100)+!(year%400)")
set /a cpmDays=CPMDAYS[!month!]
set /a epoch=((((year-1970)*365+pastLeapDays+cpmDays+leap+day-1)*24+hour)*60+minute+ntzo)*60+second
rem echo.!epoch! (pastLeapDays=!pastLeapDays! cpmDays=!cpmDays! leap=!leap! ntzo=!ntzo!)

echo.!epoch!

exit /b 0

epoch.bat -- 当前 date/time

的 Unix 纪元
@echo off
setlocal enabledelayedexpansion

if "%~1" neq "" (echo.epoch.bat: usage: too many arguments.& exit /b 1)

call dt2epoch.bat !date:~0,4! !date:~5,2! !date:~8,2! !time:~0,2! !time:~3,2! !time:~6,2!

exit /b 0

modepoch.bat -- 文件的 Unix 纪元 modification timestamp

@echo off
setlocal enabledelayedexpansion

if "%~1" equ "" (echo.modepoch.bat: usage: missing {filename}.& exit /b 1)
if "%~2" neq "" (echo.modepoch.bat: usage: too many arguments.& exit /b 1)

if not exist "%~1" (echo.modepoch.bat: usage: file "%~1" does not exist.& exit /b 1)

set dt=%~t1
set year=!dt:~0,4!
set month=!dt:~5,2!
set day=!dt:~8,2!
set hour=!dt:~11,2!
set minute=!dt:~14,2!
rem unfortunately, file mod timestamp doesn't come with seconds; just set to zero
set second=00

call dt2epoch.bat !year! !month! !day! !hour! !minute! !second!

exit /b 0

modage.bat -- 自文件 modification timestamp

以来经过的秒数
@echo off
setlocal enabledelayedexpansion

if "%~1" equ "" (echo.modage.bat: usage: missing {filename}.& exit /b 1)
if "%~2" neq "" (echo.modage.bat: usage: too many arguments.& exit /b 1)

set fileName=%~1
if not exist "!fileName!" (echo.modage.bat: usage: file "!fileName!" does not exist.& exit /b 1)

for /f %%i in ('epoch.bat') do set epoch=%%i
for /f %%i in ('modepoch.bat "!fileName!"') do set modepoch=%%i

set /a diff=epoch-modepoch
echo.!diff!

exit /b 0

checkage.bat -- 测试文件 (modification) 是否早于或晚于给定的秒数

@echo off
setlocal enabledelayedexpansion

if "%~1" equ "" (echo.checkage.bat: usage: missing {filename}.& exit /b 1)
if "%~2" equ "" (echo.checkage.bat: usage: missing {age}.& exit /b 1)
if "%~3" neq "" (echo.checkage.bat: usage: too many arguments.& exit /b 1)

set fileName=%~1
if not exist "!fileName!" (echo.checkage.bat: usage: file "!fileName!" does not exist.& exit /b 1)
set age=%~2

for /f %%i in ('modage.bat "!fileName!"') do set modage=%%i

set /a diff=modage-age
if "!diff:~0,1!" neq "-" goto older
goto younger

:older
echo.older
goto eof

:younger
echo.younger
goto eof

:eof
exit /b 0

基于大量测试,这些脚本目前可以在我的系统上运行,但有一些必须提及的注意事项:

  • epoch.bat 脚本硬编码了系统 !date!!time! 格式的假设,它们可以在控制面板中配置(至少 !date!是)。例如,我已将我的日期格式设置为 yyyy-MM-dd,但 IIRC,这不是默认格式。如果您的格式不同,您必须调整子字符串扩展。
  • modepoch.bat 脚本硬编码了 modification timestamp return 由 %~t1 编辑的文件格式假设。我相信同样的警告适用于此处 date/time 格式的可配置性。
  • 如您在 modepoch.bat 中所见,%~t1 没有 return 秒,而且我无法让我的系统达到 return 秒.因此,我不得不为秒字段硬编码为零。这可能会导致 modage.bat 脚本出现一些奇怪的行为;具体来说,如果你触摸一个文件然后立即得到它的年龄,你可以得到 0 到 59 之间的任何东西,因为脚本被迫假设文件在开始时是最后 mod 化的(秒=0 ) 在 mod 化的任何一分钟。
  • 作为 dt2epoch.bat 的一部分,我尝试通过解析 w32tm /tz 的输出来获取当前本地时区偏移量。这是从本地时间转换为 UTC 所必需的,因为 Unix 纪元被定义为自 1970-01-01 00:00:00 UTC 以来的秒数。不用说,这可能是这段代码中非常脆弱的部分。此外,在我看来,从该实用程序的输出来看,其输出背后的时区数据可以支持一定程度的灵活性,而我并没有费心尝试在我的代码中进行解析(而且,坦率地说,可能不会就此而言,能够使用纯 Dosbatch)。例如,看起来可能存在标准时间偏差,并且单个时区可能有两个以上(即不仅仅是标准时间和夏令时)时区偏移。但是我的代码只解析基本时区偏移量和额外的夏令时偏移量,并对这些输出行做出一些非常严格的假设。代码的这个特定部分可能不适合您。幸运的是,您可以轻松摆脱它,尽管生成的纪元值可能不会完全准确,但这些不准确值之间的比较应该仍然是正确的。

尽管有上述所有(相当重要的)警告,这段代码在我当前的系统上对我有用;我的 Unix (Cygwin) date 实用程序(具体来说,date +%s)与 epoch.bat 的输出之间取得了完美的一致,modification 时间戳和比较内容出现也要工作。

敢于使用此代码。