如何检索和更改 Windows 上文件的最后修改 time-stamp?

How to retrieve and change last modification time-stamp of a file on Windows?

我需要在 Windows 和 Linux 上实现相同的功能。

Linux部分是这样完成的:

#!/bin/sh

path_mainfunctions="../../data/scripts/mainfunctions.lua"
path_DisplayError="scripts/DisplayError.lua"
path_backup="scripts/mainfunctions.lua"

if [ -f $path_backup ]; then
    # check if $path_mainfunctions is newer
    alias stat='stat --format=%Y'
    # retrieve Last-Modified Timestamp of mainfunctions.lua
    lmt_mainfunctions=`stat $path_mainfunctions`
    # retrieve Last-Modified Timestamp of backup file
    lmt_backup=`stat $path_backup`
    if [ $lmt_mainfunctions -gt $lmt_backup ]; then
        # mainfunctions.lua is newer
        # backup, append and touch
        cp $path_mainfunctions $path_backup
        cat $path_DisplayError >> $path_mainfunctions
        touch $path_backup
    fi
else
    # backup
    cp $path_mainfunctions $path_backup

    # append DisplayError.lua to mainfunctions.lua
    cat $path_DisplayError >> $path_mainfunctions

    # touch $path_backup to make it newer than
    # modified file $path_mainfunctions
    touch $path_backup
fi

Windows 部分比较麻烦:

@ECHO off
SET path_mainfunctions="..\..\data\scripts\mainfunctions.lua"
SET path_DisplayError="scripts\DisplayError.lua"
SET path_backup="scripts\mainfunctions.lua"

@ECHO on
:: if it is the first time you install this mod
:: the mod should backup 'mainfunctions.lua'
:: automatically.
::
:: when the game is updated, the mod should
:: be able to detect such update:
::  -   if %path_mainfunctions% is newer than
::      %path_backup%, the mod will install itself
:: 
::  -   otherwise the mod will touch %path_backup%
IF EXIST %path_backup% (
    :: check if %path_mainfunctions% is newer
    ECHO f | XCOPY /d %path_mainfunctions% %path_backup%

    :: TODO How to get last modified timestamp more easily?
    :: SET DATE_MF=FORFILES %path_mainfunctions% /C "cmd /c ECHO @fdate"
    :: SET DATE_BK=FORFILES %path_backup% /C "cmd /c ECHO @fdate"
    ::
    :: TODO which date format will FORFILES command output?
    :: -    DD/MM/YYYY
    :: -    MM/DD/YYYY
    :: -    YYYY/MM/DD
    ::
    :: split the string and do math to get timestamp
    :: NOTE:
    :: -    SET /A RESULT = %VAR_A% * %VAR_B%
    ::
    :: SET TIME_MF=FORFILES %path_mainfunctions% /C "cmd /c ECHO @ftime"
    :: SET TIME_BK=FORFILES %path_backup% /C "cmd /c ECHO @ftime"
    ::
    :: TODO compare last-modified time-stamp and do something
) ELSE (
    :: Backup mainfunctions.lua
    ECHO f | XCOPY %path_mainfunctions% %path_backup%

    :: Append DisplayError.lua to mainfunctions.lua
    TYPE %path_DisplayError% >> %path_mainfunctions%

    :: touch %path_backup% to make it newer than
    :: modified file %path_mainfunctions%
    :: TODO how to touch a file in Windows ????
)

问题是我不知道如何检索和更改 Windows 上文件的最后修改 time-stamp,以防你忘记我的标题:)

如果你知道如何用VBScript解决问题,我想知道它是如何一步步实现的,谢谢:)

这里我将介绍一个纯批处理的解决方案。

Performing a touch is simple,虽然完全不直观。

copy /b "somepath\file.ext"+,, "somepath\file.ext" >nul

可以比较文件时间戳,但非常复杂。你可以use WMIC to get the last modified timestamp down to fractional seconds。时间戳的格式几乎使字符串比较几乎等同于时间顺序比较。问题是时间戳包括时区偏移量,表示为与 UTC (GMT) 的分钟差。因此,在从夏令时转换为标准时间期间,每年有一个小时简单的字符串比较会提供错误的答案。如果在计算机上更改了时区,您也可能得到错误的答案。可以补偿,但有一个更简单的解决方案:-)

Determining the newest file is simple if the files are all in the same folder。只需将数据文件(保留时间戳)复制到与更新文件相同的文件夹中。然后就可以用DIR命令按时间顺序列出文件,最后列出的就是最新的!

将它们放在一起,我得到:

@echo off
setlocal

:: Setup
set "dataPath=..\..\data\scripts"
set "updatePath=scripts"
set "data=mainfunctions.lua"
set "update=DisplayError.lua"

:: Make copy of original for use in date comparison and backup creation
copy /y "%dataPath%\%data%" "%updatePath%\%data%.compare" >nul

:: If this is the first install, then goto :update
if not exist "%updatePath%\%data%" goto update

:: List the update and compare files in chronological order
:: The last one listed will be the newest.
for /f "delims=" %%F in (
  'dir /b /od "%updatePath%\%data%.compare" "%updatePath%\%update%"'
) do set "newest=%%F"

:: If newest equals update then goto :update
if "%newest%" equ "%update%" goto update

:: Nothing to do, so cleanup and exit
del "%updatePath%\%data%.compare"
exit /b

:update
:: Perform the update
type "%updatePath%\%update%" >> "%dataPath%\%data%"

:: Create the backup (also effectively "removes" the compare file)
move /y "%updatePath%\%data%.compare" "%updatePath%\%data%" >nul

:: "touch" the backup to give it a last-modified date greater than the update
copy /b "%updatePath%\%data%"+,, "%updatePath%\%data%" >nul

exit /b