use*_*370 7 command-line batch-file batch-processing
很简单,我怎么知道文件夹中的特定文件是否超过X小时?文件名和位置将始终相同.
谢谢
Mof*_*ofi 11
在将文件时间与批处理代码进行比较时,必须考虑以下因素:
有环境变量DATE和TIME这对访问(而不是批处理执行的开始)返回当前在取决于格式的日期和时间的Windows区域和语言设置.国家/地区定义日期和时间格式.
甚至可以定义例如德语短日期格式DD.MM.YYYY(带有前导零的日期和月份)和时间格式HH:mm:ss(24小时格式,小时,分钟和秒的前导零).但这并不意味着DATE和TIME的值实际上是使用这种格式.例如,在选择德国国家时,即使已定义,也表示时间为格式H:mm:ss,ms,HH:mm:ss这意味着小时,但在分钟和秒,以及在逗号时间字符串后的毫秒之后没有前导零.根据区域设置,日期字符串也可以有或没有工作日.
并且存在%~t获取目录或文件的最后修改日期和时间的模式.在命令提示符窗口中运行call /?,并for /?和读取的细节这两个命令显示所有帮助页面.返回的日期和时间字符串的格式%~t以及命令DIR的输出上显示的格式也取决于Windows区域设置,但通常不等于变量DATE和TIME的格式.通常在日期/时间字符串中返回没有第二个值的文件或目录的上次修改时间.
最好的是找出在10:00 AM之前最佳执行的以下批处理文件.当前用户当前机器的格式是什么.
@echo off
echo Current date/time: %DATE% %TIME%
for %%I in ("%~f0") do echo Batch file time: %%~tI
pause
Run Code Online (Sandbox Code Playgroud)
在Windows文件系统上,文件时间使用两种存储格式:
在使用NTFS的存储介质上,使用NTFS 精确时间,该时间是自1601年1月1日凌晨12:00(协调世界时(UTC))起经过的64位数100纳秒间隔.
在使用FAT,FAT16,FAT32或exFAT的存储介质上,文件时间使用DOS日期时间格式存储,具有两个16位值,分辨率为2秒并使用当前本地时间.
这意味着对于FAT媒体上的文件,但在NTFS媒体上,奇数秒是不可能的.将最后修改时间为奇秒的NTFS驱动器上的文件复制到FAT32驱动器会导致文件相同,上次修改时间差异为1秒.
NTFS媒体上的文件时间以UTC格式存储.那么,什么是由归国%~t或命令DIR以及什么是在Windows资源管理器中显示例如取决于
更改这4个参数中的任何一个都会立即更改NTFS存储介质上文件和目录的所有显示文件时间.
FAT介质上的文件时间或多或少与创建,修改或上次访问时使用本地时间一致,但请进一步阅读以获取详细信息.
由于NTFS媒体上的文件时间以UTC格式存储,但以本地时间显示,因此该时区的当前时区和夏令时对于文件时间比较非常重要,尤其是对于NTFS和FAT32驱动器上的文件时.
但是对于FAT媒体上的文件,时区和夏令时设置可能很重要,具体取决于Windows的版本.请阅读以下详细信息.
有夏令时自动调整的设置,默认启用时变得很重要,当前设置的时区定义了夏令时调整.
例如,夏令时在欧洲是活跃的.在Windows的时钟设置中禁用此选项会导致NTFS介质上显示的文件时间立即更改-1小时,并且FAT介质上的许多文件也会因Windows版本而异.
在比较NTFS和FAT介质上的文件时间时,必须考虑由夏令时调整引起的1小时时差.
所有Windows NT版本都支持NTFS.支持NTFS的所有Windows版本上的文件和目录的文件时间行为相同.
但是如何解释FAT媒体上的文件时间取决于Windows的版本.在Windows Vista之前,FAT媒体上的文件时间与时区变化,夏令时设置和夏令时自动调整无关.在Windows 2000和Windows XP上,文件的上次修改日期/时间是固定的.
但在Windows Vista及更高版本中,FAT媒体上显示的文件时间取决于夏令时和自动调整夏令时.时区并不重要.选择当前使用的另一个时区不会像在NTFS媒体上的文件那样更改FAT媒体上文件的显示文件时间.但是,如果当前时间在活动时区的夏令时时间段内并且启用了夏令时自动调整并且文件或目录的本地时间在夏令时期间,则Windows Vista会添加+1小时然后.在标准时间内在FAT驱动器上最后修改的文件在一年中是不变的; 只是在DST时段内最后修改的文件显示有或没有+1小时,具体取决于启用自动DST调整的当前时间.
当在Windows 7机器上的FAT32驱动器上具有文件夹的公共共享并且使用Windows XP机器连接到该公共文件夹时,不同的FAT文件时间管理可能非常混乱.最近修改于2015-09-19 17:39:08的文件存储在Windows 7 PC上的FAT32驱动器上今天由带有德文时区的Windows 7显示,文件时间为19.09.2015 17:39:08,但是在2个月内未经19.09.2015 16:39:08修改,Windows XP今天在连接的Windows 7 PC上显示相同的文件,将来文件时间为19.09.2015 17:39:08.
将存档在档案(ZIP,RAR,...)中的文件的文件时间与NTFS或FAT媒体上的文件进行比较可能真的是一场噩梦.
对于此任务,将文件的上次修改时间与当前时间进行比较,仅考虑日期和时间格式设置就足够了.
下面的批处理代码使用我在批处理文件的答案中详细解释的代码来删除超过N天的文件.在使用下面的代码之前,应该阅读此解释.
根据变量DATE和TIME的日期/时间格式以及%~tI本地Windows PC上的文件返回的日期/时间字符串,可能需要对代码进行少量修改.批处理代码的注释行中给出了适当的提示.
@echo off
setlocal EnableExtensions
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 "%DateTime: AM=%" NEQ "%DateTime%" (
set "DateTime=%DateTime: AM=%"
) else if "%DateTime: PM=%" NEQ "%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%" EQU "0" ( if "%Month:~1%" NEQ "" set "Month=%Month:~1%" )
if "%Day:~0,1%" EQU "0" ( if "%Day:~1%" NEQ "" set "Day=%Day:~1%" )
if "%Hour:~0,1%" EQU "0" ( if "%Hour:~1%" NEQ "" set "Hour=%Hour:~1%" )
if "%Minute:~0,1%" EQU "0" ( if "%Minute:~1%" NEQ "" set "Minute=%Minute:~1%" )
if "%Second:~0,1%" EQU "0" ( if "%Second:~1%" NEQ "" 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 2 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
Run Code Online (Sandbox Code Playgroud)
rojo添加了有关如何使用wmic(Windows Management Instrumentation命令行实用程序)忽略日期和时间格式设置,文件系统和Windows版本的信息.
使用wmic具有固定格式的日期/时间字符串的优点,因此批处理代码适用于所有Windows计算机,无需适应本地日期/时间格式.
由于GetFileTime函数的内部使用(最有可能),因此使用wmic版本的Windows也无关紧要.
文件系统对于评估本地时间/文件时间到UTC的分钟偏移量也很重要.FAT驱动器上的命令wmic仅返回+***到UTC的分钟偏移量,而分钟偏移量对于NTFS驱动器上文件的最后修改文件时间是正确的.
NTFS和FAT32驱动器上相同文件的示例:
NTFS: 20071011192622.000000+120
FAT32: 20071011192622.000000+***
Run Code Online (Sandbox Code Playgroud)
+120是CET(中欧时间)+60分钟和活跃夏令时+60分钟之和,换句话说CEST(中欧夏令时)+120分钟.
因此,下面的批处理代码不会计算UTC的分钟偏移量,这是将文件的上次修改文件时间与当前本地时间进行比较时不需要的.
此外,必须始终在wmic命令行中使用完整路径指定文件名.只指定当前目录中的文件的文件名或具有相对路径的文件名不起作用.并且必须使用路径以文件名中的一个反斜杠转义每个反斜杠.
使用wmic的主要缺点是速度.根据Process Monitor日志(几次运行的平均值),上面的批处理代码需要在我的计算机上大约50毫秒完成.调用wmic两次的批处理代码需要完成大约1500 ms的相同任务(也是平均值).因此,如果可以避免因为本地日期/时间格式已知,那么在大量文件上使用wmic绝对不是一个好主意.
@echo off
setlocal EnableExtensions
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 echo 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%" EQU "0" ( if "%Month:~1%" NEQ "" set "Month=%Month:~1%" )
if "%Day:~0,1%" EQU "0" ( if "%Day:~1%" NEQ "" set "Day=%Day:~1%" )
if "%Hour:~0,1%" EQU "0" ( if "%Hour:~1%" NEQ "" set "Hour=%Hour:~1%" )
if "%Minute:~0,1%" EQU "0" ( if "%Minute:~1%" NEQ "" set "Minute=%Minute:~1%" )
if "%Second:~0,1%" EQU "0" ( if "%Second:~1%" NEQ "" set "Second=%Second:~1%" )
rem Must use 2 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
Run Code Online (Sandbox Code Playgroud)
这个问题的解决方案将在很大程度上取决于预期的时间范围,因为据我所知,如果没有外部程序,您就无法在批处理文件中获得作为一个整数的时间。这意味着您必须解析脚本中的时间值,解析量和所需的计算次数取决于您需要它工作的范围。这是一个简单的解决方案。它假定该文件不能早于 24 小时。
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
Run Code Online (Sandbox Code Playgroud)