如何在Windows上检索和更改文件的最后修改时间戳?

时间:2016-06-25 09:22:31

标签: windows batch-file vbscript batch-processing

我需要在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上检索和更改文件的最后修改时间戳,以防您忘记我的标题:)

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

1 个答案:

答案 0 :(得分:2)

这里我将介绍一种纯批量解决方案。

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