How do I change the file creation date of a Windows file?
Solution 1
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()
Solution 2
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://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
.
Solution 3
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)
Solution 4
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.
Solution 5
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). 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
Claudiu
Graduated from Brown University. E-mail: [email protected]
Updated on July 09, 2022Comments
-
Claudiu almost 2 years
How do I change the file creation date of a Windows file from Python?
-
jfs about 13 yearsmodification, access times could be changed by
os.utime()
docs.python.org/library/os.html#os.utime -
Claudiu about 13 years@Sebastian: thanks for the links. i looked at the SO questions, they said there no platform-independent way to do it as for example linux doesn't store file creation times
-
Claudiu about 13 years@David: hah nice, i'll remember that. what do you do for comments?
-
jfs about 13 years@Claudiu: I've posted it for readers who search google for
"python change file date windows"
. Your question is the second link. -
Claudiu about 13 years@Sebastian: ah got it, makes sense
-
Tobias Kienzler over 9 yearsSame question for Linux: stackoverflow.com/q/887557/321973
-
-
netvope about 13 yearsIf you get an ImportError and wonder where you could find
pywintypes
(as I did): sourceforge.net/projects/pywin32 -
JJC about 12 yearsUnfortunately, I'm pretty sure this only changes the file modification time and access time, not the file creation time, as the OP desires.
-
Ethan Furman about 12 yearsOn XP at least it sets the creation time.
-
Ethan Furman about 12 years@Delta's solution is much simpler.
-
SilverbackNet almost 12 yearsDoesn't do anything on XP or Win7 for me, the atime sets accesstime and mtime sets modifiedtime, neither sets creationtime.
-
Vlad about 7 yearsError using python 3: type object 'datetime.datetime' has no attribute 'datetime'
-
panda-34 about 7 years@Vlad it's an error using incorrect import statements. The object is datetime.datetime as in my example, not datetime.datetime.datetime as you're trying to use it.
-
Vlad about 7 yearsyou're right - I've change the import statement but now the error is
a float is required
fordatetime.datetime.utcfromtimestamp(newtime)
. It would be great to have this work in python 3. -
Mark Ransom over 5 yearsWhy is it so hard to find out that
win32file
is part ofpywin32
? 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. -
Mark Ransom over 5 yearsP.S. Anybody who needs a timestamp from a
datetime
object can find the answer here: stackoverflow.com/q/7852855/5987 -
Tomasz Gandor about 5 yearsFor directories: see here: stackoverflow.com/questions/4998814/… !
-
Tomachi over 4 yearsI like this "yak shaving" indeed this feels like what I am trying to do to support the Wintendo operating system. :)
-
Bruce Dawson over 4 yearsThis code would be more useful if the meanings of the magic numbers were explained. My guesses are: - epoch is time in seconds? Since when? Maybe it doesn't matter? - 10000000 is a conversion factor between seconds and WIndows' 100 ns time units - 116444736000000000 is, well, I have no idea. It seems to be a time span of ~369 years, but I can't really tell.
-
Delgan over 4 years@BruceDawson This comes from the Microsoft documentation: How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME.
-
Bruce Dawson over 4 yearsThanks. That helps give context to the meaning of some of the magic numbers. It would still be good to document them in your answer, including the still unexplained 1561675987.509 number, which I guess is just a randomly selected time?
-
Delgan over 4 years@BruceDawson Sure, I added some comments to the code snippet. ;)
-
Eryk Sun over 3 years
GENERIC_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 requestFILE_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)
. -
Eryk Sun over 3 yearsThe project on GitHub should be updated to use
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
and raise exceptions viaraise ctypes.WinError(ctypes.get_last_error())
. This (1) isolates it from other packages that use the global library loaderctypes.windll
, which caches loaded libraries, which cache function pointers, and (2) reliably captures the thread's last error value in C immediately after the FFI call. -
Delgan over 3 yearsThanks for your suggestion @ErykSun, I will make the update whenever I have some time (otherwise feel free to open a PR). Please, can you explain me why should I explicitly call
ctypes.get_last_error()
while raising aWinError()
? Reading the documentation, I thoughtGetLastError()
was automatically called anyway. -
Eryk Sun over 3 yearsUsing ctypes to call
GetLastError()
via FFI leaves a lot of executed code between the original FFI call and theGetLastError()
FFI call -- since Python is an interpreted scripting language. Loading the DLL withuse_last_error=True
automatically configures all function pointers created from it (e.g.kernel32.CreateFileW
) to use a thread-local variable to set and capture the value ofGetLastError()
in C before and after the FFI call.ctypes.get_last_error()
returns this thread-local last error value, andctypes.set_last_error(error_code)
sets it. -
Delgan over 3 years@ErykSun I think I got it, thanks a lot for the clarification! I will update
win32-setctime
as soon as possible. -
Roger Heathcote almost 3 yearsThis is super useful, thank you for making and explaining it.
-
Zertrin about 2 yearsI used it today, and it worked well for my use case. Thanks for making it and sharing it!