获取文件创建和修改日期/时间的最佳跨平台方法是什么,适用于 Linux 和 Windows?
pathlib
而不是 os
,请参阅@StevenC.Howell 的答案。也许甚至可以将接受的答案更改为 pathlib
答案?
pathlib
正在包装 os
,然后问使用 pathlib
有什么意义呢?据我了解,答案是 pathlib
的命名空间比 os
小,通常会产生更简洁的代码。
os
并浪费了时间和精力,因此发表了评论。您可以通过快速 Internet 搜索找到更多 pathlib
与 os
。
以跨平台方式获取某种修改日期很容易 - 只需调用 os.path.getmtime(path)
,您将获得上次修改 path
处的文件时的 Unix 时间戳。
另一方面,获取文件创建日期是繁琐且依赖于平台的,甚至在三大操作系统之间也有所不同:
在 Windows 上,文件的 ctime(记录在 https://msdn.microsoft.com/en-us/library/14h5k7ff.aspx)存储其创建日期。您可以在 Python 中通过 os.path.getctime() 或调用 os.stat() 的结果的 .st_ctime 属性来访问它。这在 Unix 上不起作用,其中 ctime 是最后一次更改文件的属性或内容。
在 Mac 以及其他一些基于 Unix 的操作系统上,您可以使用调用 os.stat() 的结果的 .st_birthtime 属性。
在 Linux 上,这目前是不可能的,至少在没有为 Python 编写 C 扩展的情况下是不可能的。尽管一些 Linux 常用的文件系统确实存储了创建日期(例如,ext4 将它们存储在 st_crtime 中),但 Linux 内核没有提供访问它们的方法;特别是,它从 C 中的 stat() 调用返回的结构,从最新的内核版本开始,不包含任何创建日期字段。您还可以看到,标识符 st_crtime 目前在 Python 源代码中的任何地方都没有。至少如果你在 ext4 上,数据会附加到文件系统中的 inode 上,但没有方便的方法来访问它。 Linux 上最好的方法是通过 os.path.getmtime() 或 os.stat() 结果的 .st_mtime 属性访问文件的 mtime。这将为您提供上次修改文件内容的时间,这对于某些用例可能已经足够了。
将所有这些放在一起,跨平台代码应该看起来像这样......
import os
import platform
def creation_date(path_to_file):
"""
Try to get the date that a file was created, falling back to when it was
last modified if that isn't possible.
See http://stackoverflow.com/a/39501288/1709587 for explanation.
"""
if platform.system() == 'Windows':
return os.path.getctime(path_to_file)
else:
stat = os.stat(path_to_file)
try:
return stat.st_birthtime
except AttributeError:
# We're probably on Linux. No easy way to get creation dates here,
# so we'll settle for when its content was last modified.
return stat.st_mtime
你有几个选择。一方面,您可以使用 os.path.getmtime
和 os.path.getctime
函数:
import os.path, time
print("last modified: %s" % time.ctime(os.path.getmtime(file)))
print("created: %s" % time.ctime(os.path.getctime(file)))
您的另一个选择是使用 os.stat
:
import os, time
(mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(file)
print("last modified: %s" % time.ctime(mtime))
注意:ctime()
不是指的是 *nix 系统上的创建时间,而是指上次 inode 数据更改的时间。 (感谢评论中的 kojiro for making that fact more clear,提供了一个有趣的博客文章的链接。)
ctime
会在 mtime
执行时更新(因为 mtime
是“元数据”),因此 ctime
通常是总是等于或早于 mtime
。因此,将 ctime
视为“已创建”时间毫无意义。 -1!
Last modified: Fri Jan 31 11:08:13 2020
和 Created: Fri Jan 31 11:08:13 2020
在 Linux Ubuntu 16.04 上!
time.ctime(os.path.getmtime(file))
返回 2 种类型的字符串,具体取决于文件是否已被系统或用户修改。如果它已被系统修改,则字符串将在月和日之间有 2 个空格。我不知道为什么
为此使用的最佳函数是 os.path.getmtime()。在内部,这仅使用 os.stat(filename).st_mtime
。
datetime 模块最适合处理时间戳,因此您可以将修改日期作为 datetime
对象获取,如下所示:
import os
import datetime
def modification_date(filename):
t = os.path.getmtime(filename)
return datetime.datetime.fromtimestamp(t)
使用示例:
>>> d = modification_date('/var/log/syslog')
>>> print d
2009-10-06 10:50:01
>>> print repr(d)
datetime.datetime(2009, 10, 6, 10, 50, 1)
getmtime
是 Unix 上最接近可用的东西(无法获取创建日期),但绝对不是在 Windows 上使用的最佳功能,其中 ctime
是创建时间。
datetime.datetime.fromtimestamp(t, tz=datetime.timezone.utc)
,否则返回的天真 datetime
对象倾向于被解释为位于本地时区,而 Unix 时间戳总是相对于 01.01.1970 00:00 UTC。
在 Python 3.4 及更高版本中,您可以使用面向对象的 pathlib module 接口,该接口包含大部分 os 模块的包装器。这是获取文件统计信息的示例。
>>> import pathlib
>>> fname = pathlib.Path('test.py')
>>> assert fname.exists(), f'No such file: {fname}' # check that the file exists
>>> print(fname.stat())
os.stat_result(st_mode=33206, st_ino=5066549581564298, st_dev=573948050, st_nlink=1, st_uid=0, st_gid=0, st_size=413, st_atime=1523480272, st_mtime=1539787740, st_ctime=1523480272)
有关 os.stat_result
所含内容的详细信息,请参阅 the documentation。对于您想要的修改时间 fname.stat().st_mtime
:
>>> import datetime
>>> mtime = datetime.datetime.fromtimestamp(fname.stat().st_mtime, tz=datetime.timezone.utc)
>>> print(mtime)
datetime.datetime(2018, 10, 17, 10, 49, 0, 249980)
如果您想要 Windows 上的创建时间,或 Unix 上最近的元数据更改,您可以使用 fname.stat().st_ctime
:
>>> ctime = datetime.datetime.fromtimestamp(fname.stat().st_ctime, tz=datetime.timezone.utc)
>>> print(ctime)
datetime.datetime(2018, 4, 11, 16, 57, 52, 151953)
This article 包含有关 pathlib 模块的更多有用信息和示例。
datetime.datetime.fromtimestamp(t, tz=datetime.timezone.utc)
,否则返回的天真 datetime
对象倾向于被解释为在本地时区,而 Unix 时间戳总是相对于 01.01。世界标准时间 1970 年 00:00。
在较新的代码中,您可能应该使用 os.path.getmtime() (thanks, Christian Oudard)。
但请注意,它返回 time_t 的浮点值,带有小数秒(如果您的操作系统支持它)。
os.path.getmtime()
自 Python 1.5.2(请参阅 old docs)以来一直存在,在我失去大部分乳牙之前发布,并且在您编写此答案的原始版本之前将近十年。
import os, time, datetime
file = "somefile.txt"
print(file)
print("Modified")
print(os.stat(file)[-2])
print(os.stat(file).st_mtime)
print(os.path.getmtime(file))
print()
print("Created")
print(os.stat(file)[-1])
print(os.stat(file).st_ctime)
print(os.path.getctime(file))
print()
modified = os.path.getmtime(file)
print("Date modified: "+time.ctime(modified))
print("Date modified:",datetime.datetime.fromtimestamp(modified))
year,month,day,hour,minute,second=time.localtime(modified)[:-3]
print("Date modified: %02d/%02d/%d %02d:%02d:%02d"%(day,month,year,hour,minute,second))
print()
created = os.path.getctime(file)
print("Date created: "+time.ctime(created))
print("Date created:",datetime.datetime.fromtimestamp(created))
year,month,day,hour,minute,second=time.localtime(created)[:-3]
print("Date created: %02d/%02d/%d %02d:%02d:%02d"%(day,month,year,hour,minute,second))
印刷
somefile.txt
Modified
1429613446
1429613446.0
1429613446.0
Created
1517491049
1517491049.28306
1517491049.28306
Date modified: Tue Apr 21 11:50:46 2015
Date modified: 2015-04-21 11:50:46
Date modified: 21/04/2015 11:50:46
Date created: Thu Feb 1 13:17:29 2018
Date created: 2018-02-01 13:17:29.283060
Date created: 01/02/2018 13:17:29
注意:Linux 上文件的 ctime 与 Windows 上的略有不同。 Windows 用户将其称为“创建时间”。 Linux 用户将他们称为“更改时间”。
ctime <= mtime
始终保持不变,而在 Unix 上mtime <= ctime
始终保持不变持有。您的回答表明 ctime 是文件的“创建日期”,但没有任何建议表明这根本不能移植。如果您将其称为“创建日期(在 Windows 上)”或在顶部说“此答案仅适用于 Windows”,那将是非常不同的,但这不是您在(仍然赞赏)更新答案后所做的事情。
获取 mod 时间有两种方法,os.path.getmtime() 或 os.stat(),但 ctime 跨平台不可靠(见下文)。
os.path.getmtime()
getmtime(path) 返回上次修改路径的时间。返回值是一个数字,给出自纪元以来的秒数(参见时间模块)。如果文件不存在或不可访问,则引发 os.error。版本 1.5.2 中的新功能。在 2.3 版更改: 如果 os.stat_float_times() 返回 True,则结果为浮点数。
os.stat()
stat(path) 在给定路径上执行 stat() 系统调用。返回值是一个对象,其属性对应于stat结构的成员,即:st_mode(保护位),st_ino(inode编号),st_dev(设备),st_nlink(硬链接数),st_uid(所有者的用户ID) )、st_gid(所有者的组 ID)、st_size(文件大小,以字节为单位)、st_atime(最近访问时间)、st_mtime(最近内容修改时间)、st_ctime(平台相关;最近元数据更改时间在 Unix 上,或在 Windows 上创建时间):
>>> import os
>>> statinfo = os.stat('somefile.txt')
>>> statinfo
(33188, 422511L, 769L, 1, 1032, 100, 926L, 1105022698,1105022732, 1105022732)
>>> statinfo.st_size
926L
>>>
在上面的示例中,您将使用 statinfo.st_mtime 或 statinfo.st_ctime 分别获取 mtime 和 ctime。
os.stat
返回具有 st_mtime
和 st_ctime
属性的命名元组。两个平台的修改时间都是st_mtime
;不幸的是,在 Windows 上,ctime
表示“创建时间”,而在 POSIX 上表示“更改时间”。我不知道有什么方法可以在 POSIX 平台上获得创建时间。
dir(..)
放在一个上。例如dir(os.stat(os.listdir('.')[0]))
可能值得一看 crtime
库,它实现了对文件创建时间的跨平台访问。
from crtime import get_crtimes_in_dir
for fname, date in get_crtimes_in_dir(".", raise_on_error=True, as_epoch=False):
print(fname, date)
# file_a.py Mon Mar 18 20:51:18 CET 2019
debugfs
,这在定义上是不稳定的,需要对所有内容进行顶级 root 访问,并且在几乎所有方面往往是你母亲一直警告你的事情之一。 (但是,是的,如果您真的很绝望并且碰巧是没有安全启动的系统上的真正超级用户,它可能会起作用......)
>>> import os
>>> os.stat('feedparser.py').st_mtime
1136961142.0
>>> os.stat('feedparser.py').st_ctime
1222664012.233
>>>
如果以下符号链接不重要,您还可以使用 os.lstat
内置。
>>> os.lstat("2048.py")
posix.stat_result(st_mode=33188, st_ino=4172202, st_dev=16777218L, st_nlink=1, st_uid=501, st_gid=20, st_size=2078, st_atime=1423378041, st_mtime=1423377552, st_ctime=1423377553)
>>> os.lstat("2048.py").st_atime
1423378041.0
os.stat
包含创建时间。对于包含时间的 os.stat()
元素,没有 st_anything 的定义。
所以试试这个:
os.stat('feedparser.py')[8]
将其与您在 ls -lah 中的文件上的创建日期进行比较
他们应该是一样的。
不定期副业成功案例分享
ext4
驱动器上的数据的方法,并且我想了解当 Linux 读取 Windows 写入的文件时会发生什么,反之亦然,因为它们使用 {2 } 不同。"w"
打开现有文件进行写入时,它不会替换它,它只是打开现有文件并截断它。即使文件内容与创建时的内容完全无关,您仍然会被告知该文件是在当前版本之前“创建”的。相反,在保存时使用原子替换(原始文件被新的正在进行的临时文件替换)的编辑器将显示更新的创建日期,即使您只是删除了一个字符。使用修改时间,不要贪图创建时间。stat.st_ctime
更相关,因为在许多情况下,最后一次元数据更改的时间可以是创建时间(至少ctime
更接近真正的创建时间 比mtime
)。因此,您可以简单地将您的代码段替换为stat = os.stat(path_to_file); try: return stat.st_birthtime; except AttributeError: return stat.st_ctime
。你怎么看?干杯ctime
应该始终等于或晚于mtime
,因为mtime
更改导致ctime
更改(因为mtime
本身被视为“元数据”)。请参阅 stackoverflow.com/a/39521489/1709587,其中我提供了一些示例代码来说明这一点。