How do I change the file creation date of a Windows file from Python?
12 Answers
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() 4 Comments
pywintypes (as I did): sourceforge.net/projects/pywin32GENERIC_WRITE requests data access that's not required here and either may not be granted by the file security or may lead to a sharing violation if an existing open doesn't share write-data access. The operation should only request FILE_WRITE_ATTRIBUTES metadata access, for which no data-access sharing is required, e.g. hfile = win32file.CreateFile(fname, ntsecuritycon.FILE_WRITE_ATTRIBUTES, 0, None, win32con.OPEN_EXISTING, 0, None).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.
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:
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://learn.microsoft.com/en-us/windows/win32/sysinfo/converting-a-time-t-value-to-a-file-time 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.
11 Comments
My simple and clear filedate module might accommodate your needs.
Advantages:
- Very simple interface
- Platform independent
- Fancy string dates support
- Date Holder utility
Installation
pip install filedate Usage
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" ) 1 Comment
install pywin32 extension first 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) 2 Comments
win32file is part of pywin32? Google left me high and dry, which meant none of the other answers were at all useful; they assumed you already had it installed. Thank you for the helpful hint at the top of your answer.datetime object can find the answer here: stackoverflow.com/q/7852855/5987Here'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). 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). 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 Comments
This code works on python 3 without 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() 3 Comments
a float is required for datetime.datetime.utcfromtimestamp(newtime). It would be great to have this work in python 3.import os os.utime(path, (accessed_time, modified_time)) http://docs.python.org/library/os.html
At least it changes the modification time, without using win32 module.
3 Comments
Here is a solution that works on Python 3.5 and windows 7. Very easy. 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 ) 1 Comment
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).
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) Comments
A small solution without dependencies inspired by Delgan's answer. It supports unix timestamps up to nano precision (like the values returned by os.stat(...).st_ctime_ns as an example).
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).
It requires python 3.10 for the multi-type hints used on the parameters. Just remove the hints if you want it to work for older python versions.
from ctypes import wintypes, byref, WinDLL, WinError, get_last_error def unix_ts_to_win_filetime(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].ljust(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(path: str, created_timestamp: int = None, access_timestamp: int = None, modify_timestamp: int = None) -> bool: created_timestamp = unix_ts_to_win_filetime(timestamp=created_timestamp) access_timestamp = unix_ts_to_win_filetime(timestamp=access_timestamp) modify_timestamp = 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") Comments
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:
pip install win32-setctime pip install attrs Then you can run my code, remember to update FILEPATH, DATE, MONTH and 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()
os.utime()docs.python.org/library/os.html#os.utime"python change file date windows". Your question is the second link.