Batch file 如何比较批处理脚本中文件的时间戳?

Batch file 如何比较批处理脚本中文件的时间戳?,batch-file,cmd,filesystems,Batch File,Cmd,Filesystems,在DOS批处理文件中,实现某些事情的方法有些模糊。幸运的是,有一个很棒的批处理脚本参考站点:。(同一个网站也有大量关于Bash的信息。) 一个困难是根据目录是否为空来分支执行。 明显的如果存在“%dir%\*.*”不起作用。但这可以通过以下条件执行技巧实现: ( dir /b /a "%dir%" | findstr . ) > nul && ( echo %dir% non-empty ) || ( echo %dir% empty ) 另一个棘手的问题是根据文

在DOS批处理文件中,实现某些事情的方法有些模糊。幸运的是,有一个很棒的批处理脚本参考站点:。(同一个网站也有大量关于Bash的信息。)

一个困难是根据目录是否为空来分支执行。 明显的
如果存在“%dir%\*.*”
不起作用。但这可以通过以下条件执行技巧实现:

( dir /b /a "%dir%" | findstr . ) > nul && (
  echo %dir% non-empty
) || (
  echo %dir% empty
)
另一个棘手的问题是根据文件内容进行分支。 同样,可以这样做:

( fc /B "%file1%" "%file2%" | find "FC: no differences encountered" ) > nul && (
  echo "%file1%" and "%file2%" are the same
) || (
  echo "%file1%" and "%file2%" are different
)
所以,我的问题是:
有没有办法根据文件的时间戳进行分支?

这就是我想要的东西:

REM *** pseudo-code!
if "%file1%" is_newer_than "%file2%" (
  echo "%file1%" is newer
) else if "%file1%" is_older_than "%file2%" (
  echo "%file2%" is newer
) else (
  echo "%file1%" and "%file2%" are the same age
)

谢谢。

说真的,你应该开始学点别的。这不是玩笑。DOS(cmd.exe)严重缺乏数据处理功能和更多缺陷。下面是除了DOS批处理之外,本机提供的下一个更好的替代方法vbscript

Set objFS = CreateObject("Scripting.FileSystemObject")
Set objArgs = WScript.Arguments
strFile1 = objArgs(0)
strFile2 = objArgs(1)
Set objFile1 = objFS.GetFile(strFile1)
Set objFile2 = objFS.GetFile(strFile2)
If objFile1.DateLastModified < objFile2.DateLastModified Then
    WScript.Echo "File1: "&strFile1&" is older than "&strFile2
Else
    WScript.Echo "File1: "&strFile1&" is newer than "&strFile2
End If 
Set objFS=CreateObject(“Scripting.FileSystemObject”)
Set objArgs=WScript.Arguments
strFile1=objArgs(0)
strFile2=objArgs(1)
设置objFile1=objFS.GetFile(strFile1)
设置objFile2=objFS.GetFile(strFile2)
如果objFile1.DateLastModified
在命令行上运行它

C:\test>dir
 Volume in drive C has no label.
 Volume Serial Number is 08AC-4F03

 Directory of C:\test

11/06/2009  07:40 PM    <DIR>          .
11/06/2009  07:40 PM    <DIR>          ..
11/06/2009  06:26 PM               135 file
11/02/2009  04:31 PM             4,516 m.txt

C:\test>cscript /nologo test.vbs file m.txt
File1: file is newer than m.txt
C:\test>dir
驱动器C中的卷没有标签。
卷序列号为08AC-4F03
C:\test目录
2009年6月11日晚上7:40。
2009年6月11日晚上7:40。。
11/06/2009 06:26 PM 135文件
11/02/2009 04:31 PM 4516 m.txt
C:\test>cscript/nologo test.vbs文件m.txt
File1:文件比m.txt新

当然,在较新版本的windows中,您可能希望试用Powershell…

您可以找到两个文件中较新的一行批处理脚本。只需按日期顺序列出文件,最旧的优先,这意味着列出的最后一个文件必须是较新的文件。因此,如果每次保存文件名,则变量中的姓氏将是最新的文件

例如:

SET FILE1=foo.txt
SET FILE2=bar.txt
FOR /F %%i IN ('DIR /B /O:D %FILE1% %FILE2%') DO SET NEWEST=%%i
ECHO %NEWEST% is (probably) newer.
不幸的是,这不适用于日期戳相同的情况。因此,我们只需首先检查文件是否具有相同的日期和时间戳:

SET FILE1=foo.txt
SET FILE2=bar.txt

FOR %%i IN (%FILE1%) DO SET DATE1=%%~ti
FOR %%i IN (%FILE2%) DO SET DATE2=%%~ti
IF "%DATE1%"=="%DATE2%" ECHO Files have same age && GOTO END

FOR /F %%i IN ('DIR /B /O:D %FILE1% %FILE2%') DO SET NEWEST=%%i
ECHO Newer file is %NEWEST%

:END

Dave Webb的soution虽然是一个伟大的soution,但它当然只适用于同一目录中的文件

这是一个可以处理任意两个文件的解决方案

首先获取文件时间(请参阅)

但是,由于Cmd.exe会将日期和时间作为一个sting进行比较,因此必须手动将日期和时间分解为它的组件,因此2>10和10:00AM>2:00PM

首先比较几年,然后是几个月,然后是一天,然后是上午/下午,然后是小时,然后是分钟和秒(实际上很费时,但我没有更好的办法),最后看最后的代码

但是,如果文件在同一分钟内但在第二分钟内不同,则此解决方案将不起作用

如果要达到此精度级别,请使用“forfiles”命令获取filetime(请参阅)

请注意,“ForFiles”有一个限制,即它不能采用带空格的路径,因此如果您有带空格的路径,则必须首先更改到该目录,请参阅

比较代码

:compareFileTime
set "originalFileTime=%1"
set "secondFileTime=%2"

for /F "tokens=1,2,3 delims= " %%a in (%originalFileTime%) do ( 
    set "originalDatePart=%%a"  
    set "originalTimePart=%%b"  
    set "originalAmPmPart=%%c"  
)
for /F "tokens=1,2,3 delims= " %%a in (%secondFileTime%) do (
    set "secondDatePart=%%a"
    set "secondTimePart=%%b"
    set "secondAmPmPart=%%c"
)
for /F "tokens=1,2,3 delims=/" %%a in ("%originalDatePart%") do (
        set "originalMonthPart=%%a"
        set "originalMonthDayPart=%%b"
        set "originalYearPart=%%c"

        rem We need to ensure that the year is in a 4 digit format and if not we add 2000 to it
        rem Cmd considers "50" > "100" but 50 < 100, so don't surround it with qoutes
    if %%c LSS 100 set "originalYearPart=20%%c
)
for /F "tokens=1,2,3 delims=/" %%a in ("%secondDatePart%") do (
    set "secondMonthPart=%%a"
    set "secondMonthDayPart=%%b"
    set "secondYearPart=%%c"    

    rem We need to ensure that the year is in a 4 digit format and if not we add 2000 to it
    rem Cmd considers "50" > "100" but 50 < 100, so don't surround it with quotes
        if %%c LSS 100 set "secondYearPart=20%%c    
)

if %originalYearPart% GTR %secondYearPart% goto newer
if %originalYearPart% LSS %secondYearPart% goto older

rem We reach here only if the year is identical
rem Cmd considers "2" > "10" but 2 < 10, so don't surround it with quotes or you will have to set the width explicitly
if %originalMonthPart% GTR %secondMonthPart% goto newer
if %originalMonthPart% LSS %secondMonthPart% goto older

if %originalMonthDayPart% GTR %secondMonthDayPart% goto newer
if %originalMonthDayPart% LSS %secondMonthDayPart% goto older

rem We reach here only if it is the same date
if %originalAmPmPart% GTR %secondAmPmPart% goto newer
if %originalAmPmPart% LSS %secondAmPmPart% goto older

rem we reach here only if i=t is the same date, and also the same AM/PM
for /F "tokens=1 delims=:" %%a in ("%originalTimePart%") do set "originalHourPart=%%a"

for /F "tokens=1 delims=:" %%a in ("%secondTimePart%") do set "secondHourPart=%%a"

rem Cmd considers "2" > "10" but 2 < 10, so don't surround it with qoutes or you will have to set the width explicitly
if %originalHourPart% GTR %secondHourPart% goto newer
if %originalHourPart% LSS %secondHourPart% goto older

rem The minutes and seconds can be compared directly
if %originalTimePart% GTR %secondTimePart% goto newer
if %originalTimePart% LSS %secondTimePart% goto older
if %originalTimePart% EQU %secondTimePart% goto same

goto older
exit /b

:newer
echo "newer"
exit /b

:older
echo "older"
exit /b

:same
echo "same"
exit /b
:比较完成时间
设置“originalFileTime=%1”
设置“secondFileTime=%2”
对于/F“令牌=1,2,3 delims=“%%a in(%originalFileTime%)do(
设置“originalDatePart=%%a”
设置“originalTimePart=%%b”
设置“originAlampPart=%%c”
)
对于/F“tokens=1,2,3 delims=“%%a in(%secondFileTime%)do(
设置“secondDatePart=%%a”
设置“secondTimePart=%%b”
设置“SecondAmpPart=%%c”
)
对于(“%originalDatePart%”中的/F“tokens=1,2,3 delims=/”%%a,请执行以下操作(
设置“originalMonthPart=%%a”
设置“originalMonthDayPart=%%b”
设置“originalYearPart=%%c”
rem我们需要确保年份为4位数格式,如果不是,我们将增加2000位
rem Cmd认为“50”>“100”,但50<100,所以不要用qoutes来包围它
如果%%c LSS 100 set“原始年份部分=20%%c
)
对于/F“tokens=1,2,3 delims=/”%%a in(“%secondDatePart%”)do(
设置“secondMonthPart=%%a”
设置“secondMonthDayPart=%%b”
设置“secondYearPart=%%c”
rem我们需要确保年份为4位数格式,如果不是,我们将增加2000位
rem Cmd考虑的是“50”>“100”,但50<100,所以不要用引号括起来
如果%%c LSS 100 set“secondYearPart=20%%c
)
如果%originalYearPart%GTR%secondYearPart%goto更新
如果%originalYearPart%LSS%secondYearPart%goto older
只有当年份相同时,我们才能到达这里
rem Cmd考虑的是“2”>“10”,但2<10,因此不要用引号括起来,否则必须显式设置宽度
如果%originalMonthPart%GTR%secondMonthPart%goto更新
如果%originalMonthPart%LSS%secondMonthPart%goto older
如果%originalMonthDayPart%GTR%secondMonthDayPart%转到较新版本
如果%originalMonthDayPart%LSS%secondMonthDayPart%goto older
只有在同一天,我们才能到达这里
如果%originalamppart%GTR%secondammpart%goto更新
如果%originalamppart%LSS%secondammpart%goto older
只有当i=t是相同的日期,并且也是相同的AM/PM时,我们才能到达这里
对于/F“tokens=1 delims=:”(“%originalTimePart%”)中的%%a,请设置“originalHourPart=%%a”
对于/F“tokens=1 delims=:”(“%secondTimePart%”)中的%%a,请设置“secondHourPart=%%a”
rem Cmd考虑“2”>“10”,但2<10,因此不要用qoutes包围它,否则必须显式设置宽度
如果%originalHourPart%GTR%secondHourPart%goto更新
如果%originalHourPart%LSS%secondHourPart%goto older
rem可以直接比较分和秒
如果%originalTimePart%GTR%secondTimePart%转到更新版本
如果%originalTimePart%LSS%secondTimePart%goto较旧
如果%originalTimePart%EQU%secondTimePart%转到相同的位置
变老
退出/b
:更新
回声“更新”
退出/b
:老年人
回声“老”
退出/b
:相同
回声“相同”
出口/
for /F "tokens=*" %%a in ('forfiles /m MyFile1.txt /c "cmd /c echo @fdate @ftime"') 
    do set File1Date=%%a
for /F "tokens=*" %%a in ('forfiles /m MyFile2.txt /c "cmd /c echo @fdate @ftime"') 
    do set File2Date=%%a    
:compareFileTime
set "originalFileTime=%1"
set "secondFileTime=%2"

for /F "tokens=1,2,3 delims= " %%a in (%originalFileTime%) do ( 
    set "originalDatePart=%%a"  
    set "originalTimePart=%%b"  
    set "originalAmPmPart=%%c"  
)
for /F "tokens=1,2,3 delims= " %%a in (%secondFileTime%) do (
    set "secondDatePart=%%a"
    set "secondTimePart=%%b"
    set "secondAmPmPart=%%c"
)
for /F "tokens=1,2,3 delims=/" %%a in ("%originalDatePart%") do (
        set "originalMonthPart=%%a"
        set "originalMonthDayPart=%%b"
        set "originalYearPart=%%c"

        rem We need to ensure that the year is in a 4 digit format and if not we add 2000 to it
        rem Cmd considers "50" > "100" but 50 < 100, so don't surround it with qoutes
    if %%c LSS 100 set "originalYearPart=20%%c
)
for /F "tokens=1,2,3 delims=/" %%a in ("%secondDatePart%") do (
    set "secondMonthPart=%%a"
    set "secondMonthDayPart=%%b"
    set "secondYearPart=%%c"    

    rem We need to ensure that the year is in a 4 digit format and if not we add 2000 to it
    rem Cmd considers "50" > "100" but 50 < 100, so don't surround it with quotes
        if %%c LSS 100 set "secondYearPart=20%%c    
)

if %originalYearPart% GTR %secondYearPart% goto newer
if %originalYearPart% LSS %secondYearPart% goto older

rem We reach here only if the year is identical
rem Cmd considers "2" > "10" but 2 < 10, so don't surround it with quotes or you will have to set the width explicitly
if %originalMonthPart% GTR %secondMonthPart% goto newer
if %originalMonthPart% LSS %secondMonthPart% goto older

if %originalMonthDayPart% GTR %secondMonthDayPart% goto newer
if %originalMonthDayPart% LSS %secondMonthDayPart% goto older

rem We reach here only if it is the same date
if %originalAmPmPart% GTR %secondAmPmPart% goto newer
if %originalAmPmPart% LSS %secondAmPmPart% goto older

rem we reach here only if i=t is the same date, and also the same AM/PM
for /F "tokens=1 delims=:" %%a in ("%originalTimePart%") do set "originalHourPart=%%a"

for /F "tokens=1 delims=:" %%a in ("%secondTimePart%") do set "secondHourPart=%%a"

rem Cmd considers "2" > "10" but 2 < 10, so don't surround it with qoutes or you will have to set the width explicitly
if %originalHourPart% GTR %secondHourPart% goto newer
if %originalHourPart% LSS %secondHourPart% goto older

rem The minutes and seconds can be compared directly
if %originalTimePart% GTR %secondTimePart% goto newer
if %originalTimePart% LSS %secondTimePart% goto older
if %originalTimePart% EQU %secondTimePart% goto same

goto older
exit /b

:newer
echo "newer"
exit /b

:older
echo "older"
exit /b

:same
echo "same"
exit /b
call :getfiledatestr path\file1.txt file1time
call :getfiledatestr path\file2.txt file2time
if %file1time% equ %file2time% (
  echo path\file1.txt is the same age as path\file2.txt to within a minute
) else if %file1time% lss %file2time% (
  echo path\file1.txt is older than path\file2.txt
) else (
  echo path\file1.txt is newer than path\file2.txt
)
goto :eof

@REM usage:
@REM :getfiledatestr file-path envvar
@REM result returned in %envvar%
:getfiledatestr
for %%f in (%1) do set getfiledatestr=%%~tf
@REM for MM/DD/YYYY HH:MM AMPM use call :appendpadded %2 %%c %%b %%a %%f %%d %%e
@REM for DD/MM/YYYY HH:MM AMPM use call :appendpadded %2 %%c %%b %%a %%f %%d %%e
@REM for YYYY/DD/MM HH:MM AMPM use call :appendpadded %2 %%a %%b %%c %%f %%d %%e
set %2=
for /f "tokens=1,2,3,4,5,6 delims=/: " %%a in ("%getfiledatestr%") do (
    call :appendpadded %2 %%c %%b %%a %%f %%d %%e
)
@goto :eof

@REM Takes an env var as the first parameter
@REM and values to be appended as the remaining parameters,
@REM right-padding all values with leading 0's to 4 places
:appendpadded
set temp_value=000%2
call :expand set %1=%%%1%%%%temp_value:~-4%%
shift /2
if "%2" neq "" goto appendpadded
set temp_value=
@goto :eof

@REM forces all variables to expand fully
:expand
%*
@goto :eof
@REM usage:
@REM :getfiledatestr file-path envvar
@REM result returned in %envvar%
:getfiledatestr


for %%A in (%1) do (
    set getfilefolderstr=%%~dpA
    set getfilenamestr=%%~nxA
)

@REM Removing trailing backslash
if %getfilefolderstr:~-1%==\ set getfilefolderstr=%getfilefolderstr:~0,-1%

@REM clear it for case that the forfiles command fails
set getfiledatestr=

for /f "delims=" %%i in ('"forfiles /p ""%getfilefolderstr%"" /m ""%getfilenamestr%"" /c "cmd /c echo @fdate @ftime" "') do set getfiledatestr=%%i
@REM old code: for %%f in (%1) do set getfiledatestr=%%~tf

set %2=

@REM consider missing files as oldest files
if "%getfiledatestr%" equ "" set %2=""

@REM Currently supported date part delimiters are /:. and space. You may need to add more delimiters to the following line if your date format contains alternative delimiters too. If you do not do that then the parsed dates will be entirely arbitrarily structured and comparisons misbehave.
for /f "tokens=1,2,3,4,5,6 delims=/:. " %%a in ("%getfiledatestr%") do (

@REM for MM/DD/YYYY HH:MM:SS AMPM use call :appendpadded %2 %%c %%b %%a %%g %%d %%e %%f
@REM for DD/MM/YYYY HH:MM:SS AMPM use call :appendpadded %2 %%b %%c %%a %%g %%d %%e %%f
@REM for YYYY/DD/MM HH:MM:SS AMPM use call :appendpadded %2 %%a %%b %%c %%g %%d %%e %%f
    call :appendpadded %2 %%c %%b %%a %%g %%d %%e %%f
)

@goto :eof


@REM Takes an env var as the first parameter
@REM and values to be appended as the remaining parameters,
@REM right-padding all values with leading 0's to 4 places
:appendpadded
set temp_value=000%2
call :expand set %1=%%%1%%%%temp_value:~-4%%
shift /2
if "%2" neq "" goto appendpadded
set temp_value=

@REM cmd is not able to compare integers larger than 1+31 bits, so lets convert them to quoted numeric strings instead. The current implementation generates numeric strings much longer than 31 bit integers worth.
call :expand set %1="%%%1%%%"

@goto :eof


@REM forces all variables to expand fully
:expand
%*
@goto :eof
for /f "delims=" %%r in ('xcopy /D /Y /f /e "%inputdir%\%source_filename%" "%outputdir%\%dest_filename%"') do (
  IF "%%r" EQU "1 File(s) copied" %build_command% "%inputdir%\%source_filename%" "%outputdir%\%dest_filename%"
)
xcopy /L /D /Y PATH_TO_FILE1 PATH_TO_FILE2|findstr /B /C:"1 " && echo FILE1 is newer!
*WasFile compares ..
.. time&date of two files (or directories),
.. the date of two files, time ignored
.. the date of a file with today-n (days)
.. time&date of a file with now-n (minutes)
Examples:
WasFile this.zip created before that.zip
WasFile this.zip modified after today-8
WasFile this.dat created before now-10
Using file stamps for created, modified (default) or accessed;
comparison: [not] before|after|sametime
Option to compare date only, ignore time: /DateLocal or /DateUTC*