Подтвердить что ты не робот

Узнайте, если файл старше 4 часов в пакетном файле

Достаточно просто, как бы узнать, является ли конкретный файл в папке старше X часов? Имя и местоположение файла всегда будут одинаковыми.

Спасибо

4b9b3361

Ответ 1

При сопоставлении времени файла с приведенным ниже кодом партии необходимо учитывать:

  • Настройки формата даты и времени
  • Файловая система носителя данных
  • Часовой пояс, летнее время
  • Автоматическая настройка для летнего времени
  • Версия Windows

1. Настройки формата даты и времени

Существуют переменные окружения DATE и ВРЕМЯ, которые при доступе (а не при запуске пакетного исполнения) возвращают текущий дата и время в формате в зависимости от Настройки региона и языка Windows. Страна определяет формат даты и времени.

Можно даже определить, например, для немецкого короткого формата даты с DD.MM.YYYY (день и месяц с начальным нулем) и формат времени с HH:mm:ss (24-часовой формат с начальным нулем для часа, минуты и секунды), Но это не означает, что значение DATE и ВРЕМЯ действительно использует этот формат. Например, ВРЕМЯ находится в формате H:mm:ss,ms, когда выбрана немецкая страна, даже с HH:mm:ss, которая означает отсутствие начального нуля в час, но минуты и секунды, а также миллисекунды после запятой во времени строка. Строка даты может быть также с рабочим днем ​​или без нее в зависимости от настроек региона.

И есть шаблон %~t, чтобы получить последнюю дату и время изменения каталога или файла. Запустите в окне командной строки call /? и for /? и прочитайте все справочные страницы, отображаемые для этих двух команд для получения подробной информации. Формат строки даты и времени, возвращаемой %~t, а также отображаемый на выходе команды DIR, зависит также от настроек региона Windows, но обычно не равен формату переменных DATE и ВРЕМЯ. Время последнего времени модификации файла или каталога обычно возвращается без второго значения в строке даты/времени.

Лучше всего узнать, что следующий пакетный файл лучше всего исполняется до 10:00 AM, каковы форматы текущего компьютера для текущего пользователя.

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

2. Файловая система носителей

В файловых системах Windows для файлов times используются следующие форматы хранения:

  • На носителе хранения с использованием NTFS используется точное время NTFS, которое является 64-разрядным число 100-наносекундных интервалов, прошедших с 12:00 1 января 1601 г. Скоординированное всеобщее время (UTC).

  • На носителе хранения, использующем FAT, FAT16, FAT32 или exFAT, время файла хранится с использованием DOS Date Time с двумя 16 -битные значения с разрешением 2 секунды и с использованием текущего локального времени.

Это означает, что нечетная секунда невозможна для файла на носителе FAT, но на носителе NTFS. Копирование файла на диске NTFS с нечетной секундой в последнем времени модификации на диск FAT32 приводит к наличию идентичных файлов с разницей в 1 секунду в последнем времени модификации.

Время файла на носителе NTFS хранится в формате UTC. Поэтому то, что возвращается %~t или командой DIR, а также то, что отображается, например, в проводнике Windows, зависит от

  • текущий часовой пояс,
  • Переход на летнее время для этого часового пояса,
  • если текущее время находится в пределах летнего периода,
  • и если в настоящее время включена автоматическая настройка для летнего времени.

Изменение любого из этих 4 параметров приводит к немедленному изменению ВСЕХ отображаемых файлов времени файлов и каталогов на носителях NTFS.

Время файла на носителях FAT более или менее постоянное, так как используется локальное время при создании, изменении или последнем доступе, но более подробно читайте подробнее.


3. Часовой пояс, летнее время

Поскольку время файла на носителе NTFS хранится в формате UTC, но отображается в локальное время, текущий часовой пояс и летнее время для этого часового пояса важны для сравнения времени файла, особенно когда это делается для файлов на дисках NTFS и FAT32.

Но также для файлов на медиатеке FAT параметры часового пояса и летнего времени могут быть важны в зависимости от версии Windows. Подробнее читайте ниже.


4. Автоматическая регулировка для летнего времени

Существует настройка автоматической регулировки для летнего времени, которая становится важной при включении по умолчанию, а текущий установленный часовой пояс определяет переход на летнее время.

Например, в настоящее время в Европе действует летнее время. Отключение этой опции в настройках часов Windows приводит к немедленному изменению отображаемого времени файла на носителе NTFS на -1 час, а также много файлов на носителях FAT в зависимости от версии Windows.

Эта разница в времени на 1 час, вызванная корректировкой времени летнего времени, должна учитываться при сравнении времени файла на носителях NTFS и FAT.


5. Версия Windows

NTFS поддерживается всеми версиями Windows NT. Поведение файлов одинаково для файлов и каталогов во всех версиях Windows, поддерживающих NTFS.

Но то, как интерпретируются файлы в файлах FAT, зависит от версии Windows. До Windows Vista время файла на носителях FAT не зависит от изменения часового пояса, настройки летнего времени и автоматической регулировки летнего времени. Дата и время последней модификации файла постоянны в Windows 2000 и Windows XP.

Но в Windows Vista и более поздних версиях время отображения файлов на FAT-носителях зависит от летнего времени и автоматической настройки для летнего времени. Часовой пояс не имеет прямого значения. Выбор другого часового пояса, который используется в данный момент, не изменяет отображаемое время файлов файлов на носителях FAT, как это происходит с файлами на носителе NTFS. Но если текущее время находится в пределах летнего периода времени активного часового пояса, и автоматическая настройка для летнего времени включена, а местное время файла или каталога находится в пределах летнего времени, +1 час добавляется Windows Vista и позже. Файлы, последние измененные на дисках FAT в стандартное время, постоянны в течение года; только файлы, последние измененные в период DST, отображаются с +1 или минус +1 час в зависимости от текущего времени с включенной автоматической настройкой DST.

Это другое временное управление FAT файлами может быть очень запутанным, если у вас есть общий доступ к папке на диске FAT32 на компьютере под управлением Windows 7 и подключен к этой общей папке с помощью компьютера под управлением Windows XP. Файл, последний измененный в 2015-09-19 17:39:08, хранящийся на диске FAT32 на ПК с Windows 7, сегодня отображается Windows 7 с немецким часовым поясом с файлом 19.09.2015 17:39:08, но через 2 месяца не изменен с 19.09.2015 16:39:08, и Windows XP отображает тот же файл на подключенном ПК Windows 7 сегодня и в будущем постоянный с файлом 19.09.2015 17:39:08.

Сравнение файлов файлов, хранящихся в архивах (ZIP, RAR,...) с файлами на носителях NTFS или FAT, может быть действительно кошмаром.


6. Сравнение времени файла с текущим временем

Для этой задачи, сравнивающей последнее время модификации файла с текущим временем, должно быть достаточно просто учитывать параметры формата даты и времени.

Ниже приведенный код пакета использует код, подробно описанный в моем ответе Пакетный файл для удаления файлов старше N дней. Это объяснение следует прочитать перед использованием кода ниже.

В зависимости от формата даты и времени переменных DATE и ВРЕМЯ и строки даты/времени, возвращаемых %~tI для файла на локальном ПК с ОС Windows, это может быть необходимо внести небольшие изменения в код. Соответствующие подсказки даны в строках комментариев командного кода.

@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

rojo добавлена ​​информация о том, как параметры формата даты и времени, файловая система и версия Windows могут быть проигнорированы с помощью wmic - утилита командной строки инструментария управления Windows.

Использование wmic имеет преимущество фиксированного формата для строк даты/времени, поэтому пакетный код работает на всех компьютерах Windows без адаптации к локальному формату даты и времени.

Также версия Windows не имеет значения при использовании wmic из-за внутреннего использования функции GetFileTime (скорее всего,).

Файловая система становится важной только при оценке смещения минут локального времени/времени файла в UTC. Команда wmic возвращает на диски FAT только +*** для смещения минут в UTC, в то время как смещение минут правильное для последнего файла времени файла файла на диске NTFS.

Пример для того же файла на дисках NTFS и FAT32:

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

+120 составляет +60 минут для CET (Центральноевропейское время) и +60 минут для активного летнего времени, или, другими словами, +120 минут для CEST (Центральное европейское летнее время).

Поэтому приведенный ниже пакетный код не оценивает смещение минут к UTC, которое не требуется для сравнения времени последней модификации файла с текущим местным временем.

Кроме того, имя файла должно всегда указываться с полным путем в командной строке wmic. Просто указание имени файла для файла в текущем каталоге или имя файла с относительным путем не работает. И каждый обратный слэш должен быть экранирован с еще одной обратной косой чертой в имени файла с помощью пути.

Основным недостатком использования wmic является скорость. Код партии выше требует на моем компьютере около 50 мс для завершения согласно Журнал мониторинга процессов (в среднем несколько прогонов). Код партии ниже вызова wmic дважды требуется для выполнения одной задачи около 1500 мс (также среднее значение). Поэтому использование 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
@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

Ответ 2

Решение этого будет зависеть от ожидаемого диапазона времени, так как AFAIK вы не получаете время как одно целое в пакетном файле без внешних программ. Это означает, что вам нужно проанализировать значение времени в script, а количество разбора и количество необходимых вычислений зависят от диапазона, в котором вы должны работать. Вот одно простое решение. Он предполагает, что файл НЕ может быть старше 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

Ответ 3

В качестве альтернативы вы можете создать простую программу с использованием С#, например:

// 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);    
    }
  }
}

Затем эту программу можно было бы использовать для поиска всех файлов, которые старше 2 часов в таком пакетном файле:

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

Улучшенная и самокомпилирующая версия

Как уже упоминалось @Paul, можно было даже создать хакерский гибридный файл batch/С#, который будет компилироваться и запускаться сам:

@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);
        }
    }
}

И может использоваться следующим образом:

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

Ответ 4

Чистая партия ужасна в математике по дате. Что произойдет, если ваш script запускается вскоре после полуночи? Что, если проверка времени охватывает изменение летнего времени?

Я предлагаю вызывать Windows script Host и заимствования с языка, который лучше обрабатывает математику даты/времени. Здесь представлен гибридный пакет /JScript script, который легко вычислит возраст файла или каталога. Сохраните его с расширением .bat и сделайте снимок.

@if (@[email protected]) @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));

Для получения дополнительной информации о гибридных сценариях пакетной /JScript см. эту страницу GitHub. Используемый выше стиль похож на Hybrid.bat на этой странице. Этот ответ основан на другом. Для того, что стоит, PowerShell также хорошо справляется с математикой даты; но WSH выполняется намного быстрее.