ctime是否总是小于等于mtime?

12 投票
5 回答
4891 浏览
提问于 2025-04-16 09:20

在Python中使用 os.stat() 时,我可以假设st_ctime总是小于或等于st_mtime吗?如果不能,为什么呢?

这段代码会一直在Linux上运行,但如果不同的操作系统之间有区别,那了解一下会很有帮助。

5 个回答

5

请你先解释一下“早于”是什么意思,是指更新的时间还是旧的时间?你不能假设文件的创建时间(ctime)一定在文件的修改时间(mtime)之前,但通常情况下,ctime会和mtime相同或者在后面。

在Unix系统中,ctime并不是“创建时间”,而是“更改时间”。当文件内容被修改时,mtime会更新,而当文件的元数据(比如文件的属性)被修改时,ctime会更新(这也意味着每次mtime更新时,ctime也会更新),所以ctime在mtime之后是很正常的。这里有个例子:

user@ubuntu:~$ touch test
user@ubuntu:~$ chmod 600 test
user@ubuntu:~$ stat test
  File: «test»
  Size: 0          Blocks: 0          IO Block: 4096   regular empty file
Device: 700h/1792d Inode: 222375      Links: 1
Access: (0600/-rw-------)  Uid: ( 1000/    user)   Gid: ( 1000/    user)
Access: 2011-01-03 12:35:15.945973569 +0100
Modify: 2011-01-03 12:35:15.945973569 +0100
Change: 2011-01-03 12:35:24.024998291 +0100

另外,我相信在Windows系统中,ctime字段实际上是指“创建时间”,这就是Windows和Unix之间的一个操作系统差异。我在网上看到过一些相关的信息,但我建议你自己去查一下。

9

你搞错了顺序!在Linux(或者Mac,或者其他Unix系统)上,ctime 通常总是比 mtime 晚,而不是早。和Windows不同,在Windows中,ctime 是文件的创建日期,而 mtime 是文件的修改日期。在Unix系统中,它们都是修改日期,但有以下区别:

  • mtime 会在文件内容发生变化时更新
  • ctime 会在文件属性发生变化时更新,包括它的 mtime

某些版本的 stat 工具 的手册页中分别称这些为 "最后数据修改时间""最后状态变化时间"

因此,每当 mtime 更新时,ctime 也会更新。我知道的唯一能让 mtime 大于 ctime 的方法是:

既然你是在Python的上下文中提问,我们来做一个简单的Python工具,输出给定文件的 mtimectime,帮助我们演示这个。我们将在脚本中使用方便的 os.path.getctimeos.path.getmtime API,但使用 st_ctimest_mtime 属性从 stat 调用的结果也会得到完全相同的结果:

#!/usr/bin/python
import os
import sys

target_filename = sys.argv[1]

mtime = os.path.getmtime(target_filename)
ctime = os.path.getctime(target_filename)

print('mtime: %f ctime: %f' % (mtime, ctime))

我们可以将其保存为 pystat.py,使其可执行,然后在我们的Unix命令行中进行实验:

$ # Times are initially equal:
$ touch foo
$ ./pystat.py foo
mtime: 1473979539.786961 ctime: 1473979539.786961
$ 
$ # It doesn't matter how I create the file:
$ echo qwerty > bar
$ ./pystat.py bar
mtime: 1473979561.218961 ctime: 1473979561.218961
$ 
$ # 'touch'ing a created file updates both times:
$ touch foo
$ ./pystat.py foo
mtime: 1473979584.642960 ctime: 1473979584.642960
$ 
$ touch bar
$ ./pystat.py bar
mtime: 1473979592.762960 ctime: 1473979592.762960
$ 
$ # Modifying an existing file updates both times:
$ echo stuff >> foo
$ ./pystat.py foo
mtime: 1473979622.722959 ctime: 1473979622.722959
$ 
$ # Changing permissions ONLY updates the ctime:
$ chmod 777 foo
$ ./pystat.py foo
mtime: 1473979622.722959 ctime: 1473979643.542958
$ 
$ # So does moving a file:
$ mv bar baz
$ ./pystat.py baz
mtime: 1473979592.762960 ctime: 1473979659.586958
$ 
$ # Consequently, both files now have ctime > mtime
$
$ # However, we CAN manually set mtime in the future
$ # and thereby cause ctime < mtime:
$ touch --date="2041-01-01 12:34:56" foo
$ ./pystat.py foo
mtime: 2240656496.000000 ctime: 1473989678.258937
4

有些情况下,这种假设可能不成立(这很大程度上取决于操作系统的实现):

  • 时区问题。如果你在UTC+4的时区创建了一个文件,然后在当前时区是UTC-8的情况下修改它,而操作系统在后台没有使用UTC来处理所有时间戳,那么修改时间可能会比创建时间还要早。在这种情况下,现代操作系统(比如Windows、OSX、某些BSD系统或Linux)出现修改时间小于创建时间的情况是很让人意外的。
  • 重置操作系统时间。这可能会影响修改时间,从而导致这种情况。如果文件系统驱动没有相关检查的话,mtime小于ctime的情况发生的可能性会更高。
  • 通过系统调用修改时间。同样,文件系统驱动可能会有检查来避免这种不寻常的情况。

这两种情况都是可以复现的:你最好的办法是选择一些你打算支持的操作系统,测试一下这种行为。我只能提供一些推测。

另外,st_ctime不一定是“创建时间”,而是“最后状态改变时间”(来源)。utime会更新文件的ctime来源),而它的参数类型“utimbuf”中没有ctime这个成员。因此,如果操作系统和文件系统允许,ctime实际上可能会比mtime晚。os.stat的文档中实际上提到了这一点:

平台相关;在Unix上是最近一次元数据更改的时间,或在Windows上是创建时间

虽然Python隐藏了很多C语言的细节,但os.stat及其相关函数都是基于相同的C系统调用构建的,因此查看它们的规范是获取更多信息的好地方。

撰写回答