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

Posted

技术标签:

【中文标题】如何更改 Windows 文件的文件创建日期?【英文标题】:How do I change the file creation date of a Windows file? 【发布时间】: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 的同样问题:***.com/q/887557/321973 【参考方案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 )

【讨论】:

目录:见这里:***.com/questions/4998814/…!【参考方案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 对象的时间戳的人都可以在这里找到答案:***.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).

以上是关于如何更改 Windows 文件的文件创建日期?的主要内容,如果未能解决你的问题,请参考以下文章

如何在mac上使用python更改文件的创建日期?

如何更改当前系统时间日期并插入到文本文档中

怎么更改文件修改时间?

怎么修改文件修改日期

nodejs - 如何更改文件的创建时间

MacOS 和快速更改/设置文件创建日期