简体   繁体   English

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

[英]How do I change the file creation date of a Windows file?

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

Yak shaving for the win.牦牛剃毛取胜。

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()

I did not want to bring the whole pywin32 / win32file library solely to set the creation time of a file, so I made the win32-setctime package which does just that.我不想单独使用整个pywin32 / win32file库来设置文件的创建时间,所以我制作了win32-setctime包来实现这一点。

pip install win32-setctime

And then use it like that:然后像这样使用它:

from win32_setctime import setctime

setctime("my_file.txt", 1561675987.509)

Basically, the function can be reduced to just a few lines without needing any dependency other that the built-in ctypes Python library:基本上,除了内置的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)

For advanced management (like error handling), see the source code of win32_setctime.py .对于高级管理(如错误处理),请参阅win32_setctime.py的源代码

install pywin32 extension first https://sourceforge.net/projects/pywin32/files/pywin32/Build%20221/首先安装 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)
import os
os.utime(path, (accessed_time, modified_time))

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

At least it changes the modification time, without using win32 module.至少它改变了修改时间,不使用win32模块。

Here's a more robust version of the accepted answer.这是已接受答案的更强大版本。 It also has the opposing getter function.它还具有相反的吸气功能。 This addresses created, modified, and accessed datetimes.这将解决创建、修改和访问的日期时间。 It handles having the datetimes parameters provided as either datetime.datetime objects, or as "seconds since the epoch" (what the getter returns).它处理将 datetimes 参数提供为 datetime.datetime 对象或“自纪元以来的秒数”(getter 返回的内容)。 Further, it adjusts for Day Light Saving time, which the accepted answer does not.此外,它会针对夏令时进行调整,而接受的答案并未对此进行调整。 Without that, your times will not be set correctly when you set a winter or summer time during the opposing phase of your actual system time.否则,当您在实际系统时间的相反阶段设置冬季或夏季时间时,您的时间将无法正确设置。

The major weakness of this answer is that it is for Windows only (which answers the question posed).这个答案的主要弱点是它仅适用于 Windows(回答了提出的问题)。 In the future, I'll try to post a cross platform solution.将来,我会尝试发布跨平台解决方案。

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    

This code works on python 3 without ValueError: astimezone() cannot be applied to a naive datetime :此代码适用于没有ValueError: astimezone() cannot be applied to a naive datetime 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()

Here is a solution that works on Python 3.5 and windows 7. Very easy.这是一个适用于 Python 3.5 和 Windows 7 的解决方案。非常简单。 I admit it's sloppy coding... but it works.我承认这是草率的编码......但它有效。 You're welcome to clean it up.欢迎您清理它。 I just needed a quick soln.我只是需要一个快速的解决方案。

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 )

If you want to put a date instead of an epoch you can grab this code.如果您想放置日期而不是纪元,您可以获取此代码。 I used win32-setctime and attrs packages so firstly install:我使用了 win32-setctime 和 attrs 包,所以首先安装:

pip install win32-setctime
pip install attrs

Then you can run my code, remember to update FILEPATH, DATE, MONTH and YEAR.然后就可以运行我的代码了,记得更新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()

My simple and clear filedate module might accommodate your needs.我简单清晰的文件filedate模块可能会满足您的需求。

Advantages:好处:

  • Very simple interface非常简单的界面
  • Platform independent平台无关
  • Fancy string dates support花式字符串日期支持
  • Date Holder utility日期持有者实用程序

Installation安装

pip install filedate

Usage用法

import filedate

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

A small solution without dependencies inspired by Delgan's answer . Delgan 的回答启发了一个没有依赖关系的小解决方案。 It supports unix timestamps up to nano precision (like the values returned by os.stat(...).st_ctime_ns as an example).它支持高达纳米精度的 unix 时间戳(例如os.stat(...).st_ctime_ns返回的值)。
Modified, accessed and created timestamps are supported.支持修改、访问和创建的时间戳。
Unpassed/noned parameters are being ignored by the Win32 api call (those file properties won't be changed). Win32 api 调用将忽略未传递/未传递的参数(这些文件属性不会更改)。
It requires python 3.10 for the multi-type hints used on the parameters.对于参数上使用的多类型提示,它需要 python 3.10。 Just remove the hints if you want it to work for older python versions.如果您希望它适用于较旧的 python 版本,只需删除提示即可。

from ctypes import wintypes, byref, WinDLL, WinError, get_last_error


def __unix_ts_to_win_filetime(self, timestamp: int | None) -> wintypes.FILETIME:
    if not timestamp:
        return wintypes.FILETIME(0xFFFFFFFF, 0xFFFFFFFF)

    # difference in ticks between 16010101 and 19700101 (leapseconds were introduced in 1972 so we're fine)
    _EPOCH_OFFSET_TICKS = 116444736000000000
    # truncate timestamp to 19 decimals or fill it up with zeroes
    timestamp = int(str(timestamp)[:19].rjust(19, '0'))
    timestamp_in_ticks = int(timestamp / 100)
    # add epoch offset to timestamp ticks
    timestamp_in_ticks += _EPOCH_OFFSET_TICKS
    # convert to wintypes.FILETIME by filling higher (32-bit masked) and lower number (shifted by 32 bits)
    return wintypes.FILETIME(timestamp_in_ticks & 0xFFFFFFFF, timestamp_in_ticks >> 32)

def __set_times_on_file(self, path: str, created_timestamp: int = None, access_timestamp: int = None, modify_timestamp: int = None) -> bool:
    created_timestamp = self.__unix_ts_to_win_filetime(timestamp=created_timestamp)
    access_timestamp = self.__unix_ts_to_win_filetime(timestamp=access_timestamp)
    modify_timestamp = self.__unix_ts_to_win_filetime(timestamp=modify_timestamp)

    # Win32 API call for CreateFileW and SetFileTime
    kernel32 = WinDLL("kernel32", use_last_error=True)
    hndl = kernel32.CreateFileW(path, 256, 0, None, 3, 128, None)
    if hndl == -1:
        print(WinError(get_last_error()))
        return False

    if not wintypes.BOOL(kernel32.SetFileTime(hndl, byref(created_timestamp), byref(access_timestamp), byref(modify_timestamp))):
        print(WinError(get_last_error()))
        return False

    if not wintypes.BOOL(kernel32.CloseHandle(hndl)):
        print(WinError(get_last_error()))
        return False

    return True

Usage example使用示例

if __set_times_on_file(path='C:\Windows\Temp\foo.bar', created_timestamp=1657101345298000000):
    print("file timestamps could be set")
else:
    print("file timestamps could not be set")

I could not find a straight answer for python exactly, so i am leaving an answer for anyone searching how to modify the dates for a directory (or a file, thanks to the answers in this thread).我无法准确找到 python 的直接答案,所以我为任何搜索如何修改目录(或文件,感谢此线程中的答案)日期的人留下了答案。

import os, win32con, win32file, pywintypes


def changeCreationTime(path, time):

    try:
        wintime = pywintypes.Time(time)
        # File
        if os.path.isfile(path):
            winfile = win32file.CreateFile(path,
                                           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)
            winfile.close()
            print(f'File {path} modified')
        # Directory
        elif os.path.isdir(path):
            windir = win32file.CreateFile(path,
                                          win32con.GENERIC_WRITE,
                                          win32con.FILE_SHARE_WRITE |
                                          win32con.FILE_SHARE_DELETE |
                                          win32con.FILE_SHARE_READ,
                                          None,
                                          win32con.OPEN_EXISTING,
                                          win32con.FILE_FLAG_BACKUP_SEMANTICS,
                                          None)
            win32file.SetFileTime(windir, wintime, wintime, wintime)
            windir.close()
            print(f"Directory {path} modified")
    except BaseException as err:
        print(err)

Example:例子:

# Create a folder named example and a text file named example.txt in C:\example
changeCreationTime(r'C:\example', 1338587789)
changeCreationTime(r'C:\example\example.txt', 1338587789)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM