什么是最好的跨平台方法来获得文件的创建和修改日期/时间,并且在Linux和Windows上都能使用?
如何获得文件的创建和修改日期/时间?
pathlib
代替
os
,见@StevenC.Howell的答案。也许人们甚至可以把接受的答案改为
pathlib
的答案?
pathlib
是包裹着
os
的,然后会问,那么使用
pathlib
有什么意义?根据我的理解,答案是:
pathlib
的命名空间比
os
要小,一般来说,代码会更干净。
os
,浪费了时间和神经,因此有此评论。你可以通过快速的互联网搜索找到更多的
pathlib
与
os
。
以跨平台的方式获得某种修改日期是很容易的,只要调用
os.path.getmtime(
path
)
你会得到
path
的文件最后被修改的Unix时间戳。
Getting file 创作 另一方面,日期是复杂的,并依赖于平台,甚至在三大操作系统之间也有差异。
ctime
(documented at
https://msdn.microsoft.com/en-us/library/14h5k7ff.aspx
) stores its 创作 date. You can access this in Python through
os.path.getctime()
or the
.st_ctime
attribute of the result of a call to
os.stat()
. This
won't
work on Unix, where the
ctime
is the last time that the file's attributes
or
content were changed
.
.st_birthtime
attribute of the result of a call to
os.stat()
.
On
Linux
但目前这是不可能的,至少在不为Python写一个C扩展的情况下。尽管一些常用于Linux的文件系统
do store 创作 dates
(例如,
ext4
将它们存储在
st_crtime
中),Linux内核
没有提供访问它们的方法
;特别是它从C语言的
stat()
调用中返回的结构,截至最新的内核版本。
don't contain any 创作 date fields
.你还可以看到,标识符
st_crtime
目前并没有在任何地方出现。
Python source
.至少如果你是在
ext4
上,数据
is
附加到文件系统中的inodes,但没有方便的方法来访问它。
在Linux上最好的办法是访问该文件的
mtime
,通过以下两种方式
os.path.getmtime()
or the
.st_mtime
os.stat()
结果的属性。这将给你提供文件内容最后一次被修改的时间,这可能对某些使用情况是足够的。
把这一切放在一起,跨平台的代码应该是这样的
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)
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
我已经尽了最大努力把这个东西扔在一起(在这个过程中花了几个小时进行研究),我相信它至少是
more correct
比起以前的答案,这是一个
真的很难
我希望大家能提供任何更正、澄清或其他意见。特别是,我想构建一种在Linux下访问
ext4
驱动器上的这些数据的方法,并且我想了解当Linux读取Windows写的文件时会发生什么,或者相反,因为它们使用
st_ctime
的方式不同。
坦率地说,文件创建时间通常是相当无用的。当你用
"w"
模式打开一个现有的文件进行写入时,它并不是在替换它,它只是打开现有的文件并截断它。即使该文件的内容与它创建时的内容完全无关,你仍然会被告知该文件是在当前版本之前 "创建 "的。相反,在保存时使用原子替换的编辑器(原始文件被新的正在进行的临时文件所替换)会显示一个更近的创建日期,即使你只是删除了一个字符。使用修改时间,不要用创建时间。
经过多年的努力,我终于找到了文件创建时间的用途我正在写代码检查某些目录中的文件命名规则,所以首先我想考虑那些在该规则制定后首次命名的文件。替换整个内容(mtime)是无关紧要的:如果它已经在那里了,那么它就可以不受限制地存在。
oHo
:
嗨,马克。我提出一个简化的建议。在Linux上,返回
stat.st_ctime
更加贴切,因为在许多情况下,在一个人的生命中,他的时间是最重要的。
最后一次元数据变化
可以是创造时间(至少
ctime
更接近于真实的
创建时间
比
mtime
)。因此,你可以简单地用
stat = os.stat(path_to_file); try: return stat.st_birthtime; except AttributeError: return stat.st_ctime
替换你的片段。你怎么看?欢呼声
@olibre
"至少ctime比mtime更接近真实的创造时间"
- 不是的;这是我见过几次的说法,但这是完全错误的。除非你在你的inode中手动改变了数值,否则
ctime
应该总是等于或等于
后来
比
mtime
,因为一个
mtime
的变化
原因
一个
ctime
的变化(因为
mtime
本身被认为是 "元数据")。见
stackoverflow.com/a/39521489/1709587
其中我提供了一些示例代码来说明这一点。
Bryan Oakley
发布于
2008-12-15
0
人赞同
你有几个选择。其一,你可以使用
os.path.getmtime
和
os.path.getctime
functions:
import os.path, time
print("last modified: %s" % time.ctime(os.path.getmtime(file)))
print("created: %s" % time.ctime(os.path.getctime(file)))
Your other option is to use 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))
Note: ctime()
does not指的是*nix系统上的创建时间,而是指最后一次的inode数据改变了。(感谢Kojiro使这一事实更加明确在评论中提供一个有趣的博客文章的链接)。
kojiro
:
以防有人错过@Glyph对这个问题的评论。
ctime在POSIX系统上不是指创建时间
.我想知道在过去的三年中,有多少人浏览了这个帖子,并继续写出了有缺陷的代码。
gak
:
请记住,第一个例子给了你一个字符串,而不是一个日期时间或数字。
@kojiro 你链接的博文可以更明确地说,在Unix中,只要
mtime
更新,文件的
ctime
就会更新(因为
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))
会返回两种类型的字符串,取决于文件是被系统还是被用户修改过。如果它被系统修改过,那么字符串中的月和日之间会有两个空格。我不知道为什么
Christian Oudard
发布于
2008-12-15
0
人赞同
The best function to use for this is
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上是最接近的东西(在Unix上不可能得到创建日期),但在Windows上绝对不是最好的功能,在Windows上
ctime
是一个创建时间。
@MarkAmery - 这个答案明确标明只是关于修改时间。
ntninja
:
我强烈建议在这里使用
datetime.datetime.fromtimestamp(t, tz=datetime.timezone.utc)
,因为否则返回的天真的
datetime
对象有可能被解释为在本地时区,而Unix的时间戳总是相对于01.01.1970 00:00 UTC。
Steven C. Howell
发布于
2008-12-15
0
人赞同
在Python 3.4及以上版本中,你可以使用面向对象的
pathlib模块
接口,其中包括许多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
的更多信息,请参考文件.对于修改时间你要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)
这篇文章 has more helpful info and examples for the pathlib模块.
ntninja
:
我强烈建议,正如之前的回答所提到的,在这里使用
datetime.datetime.fromtimestamp(t, tz=datetime.timezone.utc)
,因为否则返回的天真的
datetime
对象有可能被解释为在本地时区,而Unix的时间戳总是相对于01.01.1970 00:00 UTC。
Martin Beckett
发布于
2008-12-15
0
人赞同
在较新的代码中,你可能应该使用
os.path.getmtime()
(
谢谢,Christian Oudard
).
但请注意,它返回的浮点值是
time_t
用分数秒(如果你的操作系统支持它)。
os.path.getmtime()就是为此而生的,而且更简单。
这里的 "在较新的代码中 "条款有点误导。
os.path.getmtime()
从Python 1.5.2开始就已经存在了(参见
old docs
),是在我掉了大部分乳牙之前发布的,比你写这个答案的原始版本早了近十年。
Puddle
发布于
2008-12-15
0
人赞同
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))
prints
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
注意:一个文件的ctime在Linux上与Windows上略有不同。
Windows用户将其称为 "创建时间"。
Linux用户将其称为 "变化时间"。
Puddle
:
@ntninja 你确定吗? 我只用Windows,这绝对有效。我在2015年初写了这个脚本。我发现它比这里的其他人更清楚,直奔主题,完整和自我解释。(我碰巧决定在这里查找,而不是我的旧脚本,以防有什么新东西。没有......这就是方法)
ntninja
:
哦,我的意思是说"......这不会给你文件的创建时间。
除非你是
在Windows上"。对不起!事实是,这个答案是不可移植的,而且没有提到这个事实。(Linux上的输出示例。
pastebin.com/50r5vGBE
)
ntninja
:
已经在这里留下了一些其他的评论,我将很快发布一个在(最近的)Linux上也能使用的答案。但实际上,你的帖子中唯一错误的地方是,它是只有Windows的答案,没有提到这个事实。在问题中,OP甚至特别要求提供一个兼容Windows和Linux的解决方案。因此,我认为如果你在顶部的某个地方加上这个 "细节 "会很有帮助,这样人们就不会被误导,以为ctime是他们在针对多个平台时寻找的东西。
Puddle
:
@ntninja 我刚刚意识到,你在ctime问题上指责我(和其他人)是错误的。你真正想指出的是,一个文件在Linux上的ctime和在windows上的ctime略有不同。但如果你是为Linux用户编程,你就不会试图从windows的角度提供信息。同样,你也不会试图向windows用户提供Linux的信息。这就像抱怨你不能在linux上打开cmd,而它却能打开它的版本一样。
ntninja
:
It isn’t “slightly different” on Windows vs Unix – it’s
completely different
:除非你手动更新这些值,否则在Windows上
ctime <= mtime
总是成立的,而在Unix上
mtime <= ctime
则完全相反。你的回答表明,ctime是文件的 "创建日期",而没有暗示这根本就不具有可移植性。如果你把它称为 "创建日期(在Windows上)",或者在顶部说 "这个答案只适用于Windows",情况就会大不相同,但这不是你在更新答案后所做的事情(仍然值得赞赏)。
Jay
发布于
2008-12-15
0
人赞同
有两种方法可以获得mod时间,os.路.getmtime()或os.统计数据(),但ctime在跨平台上不可靠(见下文)。
os.路.getmtime()
getmtime
(
路
)
Return the time of last modification of 路. The return value is a number giving the
number of seconds since the epoch (see the time module). Raise os.error if the file does
not exist or is inaccessible. New in version 1.5.2. Changed in version 2.3: If
os.统计数据_float_times() returns True, the result is a floating point number.
os.统计数据()
统计数据
(
路
)
Perform a 统计数据() system call on the given 路. The return value is an object whose
attributes correspond to the members of the 统计数据 structure, namely: st_mode (protection
bits), st_ino (inode number), st_dev (device), st_nlink (number of hard links), st_uid
(user ID of owner), st_gid (group ID of owner), st_size (size of file, in bytes),
st_atime (time of most recent access),
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
In the above example you would use 统计数据info.st_mtime or 统计数据info.st_ctime to get the mtime and ctime, respectively.
mithrandi
发布于
2008-12-15
0
人赞同
os.stat
返回一个带有
st_mtime
和
st_ctime
属性的命名元组。修改时间在两个平台上都是
st_mtime
;不幸的是,在Windows上,
ctime
意味着 "创建时间",而在POSIX上,它意味着 "改变时间"。我不知道有什么方法可以在POSIX平台上获得创建时间。
这里有更多关于标签图元的信息。
stackoverflow.com/questions/2970608/...
They work like tuples, but try
dir(..)
on one. E.g.
dir(os.stat(os.listdir('.')[0]))
unmounted
发布于
2008-12-15
0
人赞同
>>> import os
>>> os.stat('feedparser.py').st_mtime
1136961142.0
>>> os.stat('feedparser.py').st_ctime
1222664012.233
ntninja
:
-1:正如在其他地方提到的,这不会给你文件的创建时间,除非你是在Windows上(答案中甚至没有提到!)。
解释一下就可以了。例如,我们看到了什么?结果告诉我们什么?结论是什么?这是在哪个平台上测试的?Python和库的哪个版本?你能链接到所用属性的文档吗?
Muhammad Lukman Low
发布于
2008-12-15
0
人赞同
如果下面的符号链接不重要,你也可以使用
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
这将给出最后一次读取的时间(至少在Unix上),这
definitely
并不是要求的那样。
你的意思是
"...符号链接并不重要"
?你能详细说明一下吗?
pat Callahan
发布于
2008-12-15
0
人赞同
os.stat
确实包括了创建时间。 只是对于包含时间的
os.stat()
的元素,没有st_anything的定义。
So try this: