如何复制文件但触摸新副本上的时间戳?

Posted

技术标签:

【中文标题】如何复制文件但触摸新副本上的时间戳?【英文标题】:How to copy a file but touch the timestamp on the new copy? 【发布时间】:2014-10-22 18:11:34 【问题描述】:

我正在使用::CopyFile() 来制作文件的副本。看来原始文件的时间戳正在被保留,我希望副本在副本上设置当前时间戳,即“触摸”它。

有没有一种 WinAPI 方法可以轻松做到这一点?

【问题讨论】:

谷歌搜索winapi set file time 有一些可能性。 【参考方案1】:

如果您阅读MSDN documentation 中的CopyFile(),底部的 cmets 会说以下内容:

文件时间语义 本文应记录有关文件创建/修改/访问时间的语义。

创建时间:如果目标文件已经存在,则保留其创建时间,否则设置为当前系统时间。 上次修改时间:始终从源文件的修改时间复制。 上次访问时间:始终设置为当前系统时间。

修改时间并不总是保留 不保证设置修改时间。 CopyFileEx 确实会尝试设置修改时间,但不会对其进行错误检查。这意味着如果在 CopyFileEx 内部设置修改时间失败(例如访问被拒绝),后者仍然会返回成功!

因此,如果修改时间对您的方案很重要(它适用于我的同步程序),您必须显式调用 SetFileTime() 并检查它的返回值以确定。

您应该使用SetFileTime() 自行更新复制文件的时间戳,以确保将它们设置为您希望它们设置的值。 MSDN上有一个例子:

Changing a File Time to the Current Time

#include <windows.h>

// SetFileToCurrentTime - sets last write time to current system time
// Return value - TRUE if successful, FALSE otherwise
// hFile  - must be a valid file handle

BOOL SetFileToCurrentTime(HANDLE hFile)

    FILETIME ft;
    SYSTEMTIME st;
    BOOL f;

    GetSystemTime(&st);              // Gets the current system time
    SystemTimeToFileTime(&st, &ft);  // Converts the current system time to file time format
    f = SetFileTime(hFile,           // Sets last-write time of the file 
        (LPFILETIME) NULL,           // to the converted current system time 
        (LPFILETIME) NULL, 
        &ft);    

    return f;

【讨论】:

【参考方案2】:

::CopyFile 实际上是 windows 的一部分:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa363851%28v=vs.85%29.aspx

这是一个复制元数据的便利功能。还有另一种使用 Windows 复制文件的方法,虽然不太方便。看看这些函数:

读取文件: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467%28v=vs.85%29.aspx

创建文件: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx

写入文件: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747%28v=vs.85%29.aspx

    HANDLE WINAPI CreateFile(
      _In_      LPCTSTR lpFileName,
      _In_      DWORD dwDesiredAccess,
      _In_      DWORD dwShareMode,
      _In_opt_  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
      _In_      DWORD dwCreationDisposition,
      _In_      DWORD dwFlagsAndAttributes,
      _In_opt_  HANDLE hTemplateFile
      );

    BOOL WINAPI ReadFile(
      _In_         HANDLE hFile,
      _Out_        LPVOID lpBuffer,
      _In_         DWORD nNumberOfBytesToRead,
      _Out_opt_    LPDWORD lpNumberOfBytesRead,
      _Inout_opt_  LPOVERLAPPED lpOverlapped
      );


    BOOL WINAPI WriteFile(
      _In_         HANDLE hFile,
      _In_         LPCVOID lpBuffer,
      _In_         DWORD nNumberOfBytesToWrite,
      _Out_opt_    LPDWORD lpNumberOfBytesWritten,
      _Inout_opt_  LPOVERLAPPED lpOverlapped
      );

所以你可以这样打开文件:

CreateFile(<File>, GENERIC_READ, FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)

检查无效的返回句柄,

使用以下内容创建新文件:

CreateFile(<File>, GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL)

检查无效的返回句柄,

将文件读入缓冲区:

ReadFile(handle for file 1, buffer, Buffer size, Destination file,OUT for Bytes Read, NULL)

然后写出Buffer:

   WriteFile(outfile handle,buffer,number of bytes,NULL)

合上你的把手。

请务必阅读 CreateFiles 详细信息,它也可用于打开文件。

【讨论】:

以上是关于如何复制文件但触摸新副本上的时间戳?的主要内容,如果未能解决你的问题,请参考以下文章

windows cmd上的“触摸”等价物是啥? [复制]

使用 python 或 bash 按时间戳将音频文件复制到新文件夹

bash:使用新后缀复制每个文件

复制 Jquery Draggables

如何在工作时暂停多文件复制?

如何以依赖感知方式复制文件,同时考虑存在和时间戳