【问题标题】:How do I change the file creation date of a Windows file?如何更改 Windows 文件的文件创建日期?
【发布时间】:2011-06-27 03:41:13
【问题描述】:

如何从 Python 更改 Windows 文件的文件创建日期?

【问题讨论】:

  • 修改访问次数可以被os.utime()docs.python.org/library/os.html#os.utime修改
  • @Sebastian:感谢您的链接。我查看了 SO 问题,他们说没有独立于平台的方法,例如 linux 不存储文件创建时间
  • @David:很好,我会记住的。你为 cmets 做什么?
  • @Claudiu:我已经为那些在谷歌上搜索"python change file date windows" 的读者发布了它。您的问题是第二个链接。
  • Linux 的同样问题:stackoverflow.com/q/887557/321973

标签: python windows file date time


【解决方案1】:

我的简单 clear filedate 模块可能会满足您的需求。

优点:

  • 非常简单的界面
  • 独立于平台
  • 花式字符串日期支持
  • 日期持有者实用程序

安装

pip install filedate

用法

import filedate
Path = "~/Documents/File.txt"

filedate.File(Path).set(
    created = "1st February 2003, 12:30",
    modified = "3:00 PM, 04 May 2009",
    accessed = "08/07/2014 18:30:45"
)

【讨论】:

    【解决方案2】:

    如果您想输入日期而不是纪元,您可以获取此代码。我使用了 win32-setctime 和 attrs 包,所以首先安装:

    pip install win32-setctime
    pip install attrs
    

    然后你就可以运行我的代码了,记得更新 FILEPATH、DATE、MONTH 和 YEAR。

    from datetime import datetime
    
    import attr
    from win32_setctime import setctime
    
    FILEPATH = r'C:\Users\jakub\PycharmProjects\date_creation_change\doc.docx'
    DAY, MONTH, YEAR = (9, 5, 2020)
    
    
    @attr.s
    class TimeCounter:
        """
        Class calculates epochs
        """
        day = attr.ib(converter=str)
        month = attr.ib(converter=str)
        year = attr.ib(converter=str)
    
        def create_datetime(self):
            date_time_obj = datetime.strptime(r'{}/{}/{}'.format(self.day,
                                                                 self.month,
                                                                 self.year), '%d/%m/%Y')
    
            unix_start = datetime(1970, 1, 1)
            return (date_time_obj - unix_start).days
    
        def count_epoch(self):
            days = self.create_datetime()
            return days * 86400
    
    
    @attr.s
    class DateCreatedChanger:
        """
        Class changes the creation date of the file
        """
        file_path = attr.ib()
    
        def change_creation_date(self):
            epoch_obj = TimeCounter(day=DAY,
                                    month=MONTH,
                                    year=YEAR)
            epoch = epoch_obj.count_epoch()
            setctime(self.file_path, epoch)
    
    
    if __name__ == '__main__':
        changer = DateCreatedChanger(FILEPATH)
        changer.change_creation_date()
    

    【讨论】:

      【解决方案3】:

      我不想将整个 pywin32 / win32file 库仅仅用于设置文件的创建时间,所以我制作了 win32-setctime 包来实现这一点。

      pip install win32-setctime
      

      然后像这样使用它:

      from win32_setctime import setctime
      
      setctime("my_file.txt", 1561675987.509)
      

      基本上,除了内置的ctypes Python库之外,函数可以减少到几行,不需要任何依赖:

      from ctypes import windll, wintypes, byref
      
      # Arbitrary example of a file and a date
      filepath = "my_file.txt"
      epoch = 1561675987.509
      
      # Convert Unix timestamp to Windows FileTime using some magic numbers
      # See documentation: https://support.microsoft.com/en-us/help/167296
      timestamp = int((epoch * 10000000) + 116444736000000000)
      ctime = wintypes.FILETIME(timestamp & 0xFFFFFFFF, timestamp >> 32)
      
      # Call Win32 API to modify the file creation date
      handle = windll.kernel32.CreateFileW(filepath, 256, 0, None, 3, 128, None)
      windll.kernel32.SetFileTime(handle, byref(ctime), None, None)
      windll.kernel32.CloseHandle(handle)
      

      有关高级管理(如错误处理),请参阅the source code of win32_setctime.py

      【讨论】:

      • 如果解释了幻数的含义,这段代码会更有用。我的猜测是: - 纪元是以秒为单位的时间?从何时起?也许没关系? - 10000000 是秒和 WIndows 的 100 ns 时间单位之间的转换因子 - 116444736000000000 是,好吧,我不知道。这似乎是一个大约 369 年的时间跨度,但我无法确定。
      • @BruceDawson 这来自 Microsoft 文档:How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME
      • 谢谢。这有助于为一些神奇数字的含义提供上下文。在您的答案中记录它们仍然会很好,包括仍然无法解释的 1561675987.509 数字,我猜这只是一个随机选择的时间?
      • @BruceDawson 当然,我在代码 sn-p 中添加了一些 cmets。 ;)
      • GitHub 上的项目应该更新为使用kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) 并通过raise ctypes.WinError(ctypes.get_last_error()) 引发异常。这 (1) 将其与使用全局库加载器 ctypes.windll 的其他包隔离,后者缓存加载的库,缓存函数指针,以及 (2) 在 FFI 调用后立即可靠地捕获线程在 C 中的最后一个错误值。跨度>
      【解决方案4】:
      import os
      os.utime(path, (accessed_time, modified_time))
      

      http://docs.python.org/library/os.html

      至少改变了修改时间,不使用win32模块。

      【讨论】:

      • 不幸的是,我很确定这只会改变文件修改时间和访问时间,而不是文件创建时间,正如 OP 所希望的那样。
      • 在 XP 上至少它设置了创建时间。
      • 在 XP 或 Win7 上对我没有任何作用,atime 设置访问时间,mtime 设置修改时间,既不设置创建时间。
      【解决方案5】:

      这是一个适用于 Python 3.5 和 windows 7 的解决方案。非常简单。我承认这是草率的编码......但它的工作原理。欢迎你清理它。我只需要一个快速解决方案。

      import pywintypes, win32file, win32con, datetime, pytz
      
      def changeFileCreationTime(fname, newtime):
          wintime = pywintypes.Time(newtime)
          winfile = win32file.CreateFile(fname, win32con.GENERIC_WRITE,
                                         win32con.FILE_SHARE_READ | 
                                         win32con.FILE_SHARE_WRITE | 
                                         win32con.FILE_SHARE_DELETE,
                                         None, 
                                         win32con.OPEN_EXISTING,
                                         win32con.FILE_ATTRIBUTE_NORMAL, 
                                         None)
      
          win32file.SetFileTime(      winfile,  wintime,  wintime,     wintime)
          # None doesnt change args = file,     creation, last access, last write
          # win32file.SetFileTime(None, None, None, None) # does nonething
          winfile.close()
      
      if __name__ == "__main__":
          local_tz = pytz.timezone('Antarctica/South_Pole')
          start_date = local_tz.localize(datetime.datetime(1776,7,4), is_dst=None)
          changeFileCreationTime(r'C:\homemade.pr0n', start_date )
      

      【讨论】:

      【解决方案6】:

      先安装pywin32扩展https://sourceforge.net/projects/pywin32/files/pywin32/Build%20221/

      import win32file
      import pywintypes
      
      # main logic function
      def changeFileCreateTime(path, ctime):
          # path: your file path
          # ctime: Unix timestamp
      
          # open file and get the handle of file
          # API: http://timgolden.me.uk/pywin32-docs/win32file__CreateFile_meth.html
          handle = win32file.CreateFile(
              path,                          # file path
              win32file.GENERIC_WRITE,       # must opened with GENERIC_WRITE access
              0,
              None,
              win32file.OPEN_EXISTING,
              0,
              0
          )
      
          # create a PyTime object
          # API: http://timgolden.me.uk/pywin32-docs/pywintypes__Time_meth.html
          PyTime = pywintypes.Time(ctime)
      
          # reset the create time of file
          # API: http://timgolden.me.uk/pywin32-docs/win32file__SetFileTime_meth.html
          win32file.SetFileTime(
              handle,
              PyTime
          )
      
      # example
      changeFileCreateTime('C:/Users/percy/Desktop/1.txt',1234567789)
      

      【讨论】:

      • 为什么很难发现win32filepywin32 的一部分?谷歌让我兴奋不已,这意味着其他答案都毫无用处;他们假设您已经安装了它。感谢您在答案顶部提供的有用提示。
      • P.S.任何需要来自datetime 对象的时间戳的人都可以在这里找到答案:stackoverflow.com/q/7852855/5987
      【解决方案7】:

      这是已接受答案的更可靠版本。它还具有相反的吸气剂功能。这涉及创建、修改和访问的日期时间。它处理以 datetime.datetime 对象或“自纪元以来的秒数”(getter 返回的内容)形式提供的 datetimes 参数。此外,它会调整夏令时,而接受的答案不会。否则,当您在实际系统时间的相反阶段设置冬季或夏季时间时,您的时间将无法正确设置。

      此答案的主要弱点是它仅适用于 Windows(它回答了提出的问题)。以后我会尝试发布一个跨平台的解决方案。

      def isWindows() :
        import platform
        return platform.system() == 'Windows' 
      
      def getFileDateTimes( filePath ):        
          return ( os.path.getctime( filePath ), 
                   os.path.getmtime( filePath ), 
                   os.path.getatime( filePath ) )
      
      def setFileDateTimes( filePath, datetimes ):
          try :
              import datetime
              import time 
              if isWindows() :
                  import win32file, win32con
                  ctime = datetimes[0]
                  mtime = datetimes[1]
                  atime = datetimes[2]
                  # handle datetime.datetime parameters
                  if isinstance( ctime, datetime.datetime ) :
                      ctime = time.mktime( ctime.timetuple() ) 
                  if isinstance( mtime, datetime.datetime ) :
                      mtime = time.mktime( mtime.timetuple() ) 
                  if isinstance( atime, datetime.datetime ) :
                      atime = time.mktime( atime.timetuple() )             
                  # adjust for day light savings     
                  now = time.localtime()
                  ctime += 3600 * (now.tm_isdst - time.localtime(ctime).tm_isdst)
                  mtime += 3600 * (now.tm_isdst - time.localtime(mtime).tm_isdst)
                  atime += 3600 * (now.tm_isdst - time.localtime(atime).tm_isdst)            
                  # change time stamps
                  winfile = win32file.CreateFile(
                      filePath, win32con.GENERIC_WRITE,
                      win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
                      None, win32con.OPEN_EXISTING,
                      win32con.FILE_ATTRIBUTE_NORMAL, None)
                  win32file.SetFileTime( winfile, ctime, atime, mtime )
                  winfile.close()
              else : """MUST FIGURE OUT..."""
          except : pass    
      

      【讨论】:

        【解决方案8】:

        此代码适用于 python 3,无需 ValueError: astimezone() cannot be applied to a naive datetime:

        wintime = datetime.datetime.utcfromtimestamp(newtime).replace(tzinfo=datetime.timezone.utc)
        winfile = win32file.CreateFile(
            fname, win32con.GENERIC_WRITE,
            win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
            None, win32con.OPEN_EXISTING,
            win32con.FILE_ATTRIBUTE_NORMAL, None)
        win32file.SetFileTime(winfile, wintime)
        winfile.close()
        

        【讨论】:

        • 使用 python 3 时出错:类型对象 'datetime.datetime' 没有属性 'datetime'
        • @Vlad 使用不正确的导入语句是一个错误。该对象是我的示例中的 datetime.datetime,而不是您尝试使用它的 datetime.datetime.datetime。
        • 你是对的 - 我已经更改了导入语句,但现在错误是 a float is required for datetime.datetime.utcfromtimestamp(newtime)。在 python 3 中进行这项工作会很棒。
        【解决方案9】:

        Yak shaving 赢得胜利。

        import pywintypes, win32file, win32con
        def changeFileCreationTime(fname, newtime):
            wintime = pywintypes.Time(newtime)
            winfile = win32file.CreateFile(
                fname, win32con.GENERIC_WRITE,
                win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
                None, win32con.OPEN_EXISTING,
                win32con.FILE_ATTRIBUTE_NORMAL, None)
        
            win32file.SetFileTime(winfile, wintime, None, None)
        
            winfile.close()
        

        【讨论】:

        • 如果您收到 ImportError 并想知道在哪里可以找到 pywintypes(就像我一样):sourceforge.net/projects/pywin32
        • @Delta 的解决方案要简单得多。
        • 我喜欢这种“牦牛剃须”,确实这感觉就像我正在努力支持 Wintendo 操作系统。 :)
        • GENERIC_WRITE 请求此处不需要的数据访问权限,文件安全性可能未授予该权限,或者如果现有打开不共享写入数据访问权限,则可能导致共享冲突。该操作应该只请求FILE_WRITE_ATTRIBUTES 元数据访问,不需要数据访问共享,例如hfile = win32file.CreateFile(fname, ntsecuritycon.FILE_WRITE_ATTRIBUTES, 0, None, win32con.OPEN_EXISTING, 0, None).
        猜你喜欢
        • 1970-01-01
        • 2010-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-24
        • 2021-10-10
        • 2018-06-30
        • 1970-01-01
        相关资源
        最近更新 更多