关于文件创建时间的思考
为什么我放弃保留文件的创建时间
好久以前,我注意到文件的创建时间很容易修改掉,比如复制文件,还有把文件从一个设备剪贴到另一个设备。
但是文件创建时间有时会有特殊意义,例如照片、录像文件的创建时间表示了拍摄时间,如果我隔了一段时间对图片进行P图,或者把过去的视频进行压缩,那么创建时间就没有了意义。
所以我当时想有一段代码,可以维护文件创建时间不变。或者,可以根据一定的参照修改文件创建时间。
不过今天我发现,Linux 系统下的“创建时间”并非 Windows 系统轻易可以获取和修改,至少并非一开始就是这样。
在 Python 标准库获得的 os.stat_result
[1] 中, st_ctime
在 Linux 下为元数据修改的时间,在 Windows 下为文件创建时间。
File creation times 这篇文章有关于文件创建时间的讨论,其实这让我意识到,文件创建时间这一概念并不是多平台统一,也并非是一个普通的适合随意修改的属性。
而如果你稍加探索,就会发现很多地方可以修改文件修改时间,但是不提供修改文件创建时间的接口。
这让我思考了一下我的需求,其实我想保留文件创建时间作为文件内容的新旧程度,其实这个更应该使用文件修改时间。即使我想压缩视频并不改变文件时间,也应该放弃维护文件创建时间的不变性(因为不同文件系统下对于创建时间的概念可能都不统一),转而维护文件修改时间的不变性!这个思路是与很多工具相吻合的!(之前看到 TinyPNG API 中有保留文件修改时间的选项)
保留文件创建 & 修改时间的方式整理
最简单的方法应该是:压缩文件。
- WinRAR在压缩文件和解压时,默认保留文件、文件夹的创建日期、修改日期、访问日期 - CSDN
- 在 Linux 系统下用 zip 压缩测试,解压后文件修改时间不变,但是文件创建时间改变。
使用程序设定,例如 Windows 下,Python 中可以使用 win32 修改创建时间和修改时间。
而更通用的情况下可以使用 Python shutil.copystat
(Copy the permission bits, last access time, last modification time, and flags from src to dst.)
from win32file import CreateFile, SetFileTime, GetFileTime, CloseHandle
from win32file import GENERIC_READ, GENERIC_WRITE, OPEN_EXISTING
from pywintypes import Time
import time
def modifyFileTime(filePath,
createTime,
modifyTime,
accessTime,
format="%Y-%m-%d %H:%M:%S"):
"""
用来修改任意文件的相关时间属性
:param filePath: 文件路径名
:param createTime: 创建时间
:param modifyTime: 修改时间
:param accessTime: 访问时间
:param format: 字符串时间格式,默认 YYYY-MM-DD HH:MM:SS 例如:2019-02-02 00:01:02
"""
# str --> time.struct_time --> seconds
format = "%Y-%m-%d %H:%M:%S"
cTime = time.mktime(time.strptime(createTime, format))
mTime = time.mktime(time.strptime(modifyTime, format))
aTime = time.mktime(time.strptime(accessTime, format))
# convert to pywintypes.datetime
createTimes = Time(int(cTime))
accessTimes = Time(int(aTime))
modifyTimes = Time(int(mTime))
# set
fh = CreateFile(filePath, GENERIC_READ | GENERIC_WRITE, 0, None,
OPEN_EXISTING, 0, 0)
# createTimes, accessTimes, modifyTimes = GetFileTime(fh)
SetFileTime(fh, createTimes, accessTimes, modifyTimes)
CloseHandle(fh)
cTime = "2023-01-30 00:00:00" # 创建时间
mTime = "2023-01-30 00:00:00" # 修改时间
aTime = "2023-01-30 00:00:00" # 访问时间
fName = r"test.jpg" #文件路径
modifyFileTime(fName, cTime, mTime, aTime)
Windows 下的方法比较多(大概是因为系统本身就提供这个API)[2],有 Fast Copy 软件可以复制创建时间[3].