ctime 是不是总是 <= mtime?
Posted
技术标签:
【中文标题】ctime 是不是总是 <= mtime?【英文标题】:Is ctime always <= mtime?ctime 是否总是 <= mtime? 【发布时间】:2011-06-02 17:20:14 【问题描述】:在 Python 中使用os.stat() 时,我可以假设 st_ctime 总是小于或等于 st_mtime 吗?如果没有,为什么不呢?
代码将始终在 Linux 上运行,但如果操作系统之间存在差异,最好了解一下。
【问题讨论】:
这个问题有点糊涂,它接受的答案确实是错误的。通常mtime <= ctime
,而不是相反!请参阅my answer 以获取解释和在 shell 中的演示。
ctime
根本不是创建,而是元数据更改时间。因此,公认的答案是完全错误的:不仅仅是“某些情况”或(否则,正如该短语所暗示的那样)这种假设无效的罕见极端情况!
【参考方案1】:
请定义“小于”,您是指较新还是较旧?您不能假设 ctime 发生在 mtime 之前,但通常 ctime 与 mtime 相同或之后。
unix 上的 ctime 不是“创建时间”,而是“更改时间”。 mtime 在文件内容更改时更新,但 ctime 在文件元数据更改时更新(这意味着它也会在 mtime 更新时更新),因此 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 之间的操作系统差异。我在网上读过一些关于这方面的内容,但我会让你自己研究一下。
【讨论】:
“小于”总是在之前/之前。【参考方案2】:在某些情况下,这种假设可能被证明是无效的(并且很大程度上取决于操作系统的实现):
时区。如果您在 UTC+4 中创建一个文件,然后在当前时区为 UTC-8 时对其进行修改,并且操作系统不会在幕后对所有时间戳使用 UTC,则修改时间会更少比创建时间。对于现代操作系统(Windows、OSX、BSD 或 Linux 之一)来说,在这种情况下具有 mtime 重置操作系统时间。这可能会影响创建这种情况的修改时间。我想说的是,在这种情况下,如果没有在文件系统驱动程序中进行检查以避免这种情况,那么在没有来自操作系统的投诉的情况下,您更有可能拥有 mtime 通过系统调用修改时间。同样,文件系统驱动程序可能会进行检查以避免此类异常情况。这两者都是可重现的:最好的办法是采用您计划针对和测试这种行为的各种操作系统。我只能提供猜测。
另外,st_ctime不一定是“创建时间”,而是“最后状态变化”的时间(source)。 utime
标记要更新的文件的ctime
(source),它的“utimbuf”类型参数没有ctime
的成员。因此,如果操作系统和文件系统允许,ctime 在技术上是可能超过 mtime 的时间。 os.stat
文档实际上提到了这一点:
平台相关;大多数时间 Unix 上最近的元数据更改,或 Windows 上的创建时间
虽然 Python 隐藏了很多 C 方面的东西,但os.stat
和朋友们都建立在相同的基本 C 系统调用之上,因此他们的规范是查找更多信息的好地方。
【讨论】:
我想你在第一句话中把它弄反了,对吧? :-) “某些情况”是非常非常谨慎的语言,用于没有重要依据的假设(通常与实际情况相反,其中 ctime >= mtime) . 正如@CharlesDuffy 所说,这个答案是错误的,而且真的有点傻。查看修订版,我猜您编写了修订版 1,然后意识到ctime
!= “创建时间”,并在您的答案中编辑了一个附带条件(创建修订版 2)。问题是你(以及那些支持你的人)似乎没有注意到ctime
不是一个创建时间完全无效这个答案的整体主旨;你相当有效地在开始的段落中破坏了你自己的论点 '另外,st_ctime 不一定是“创建时间”......'【参考方案3】:
完全可以通过编程方式设置这两个值。您也可以通过将时钟设置回创建文件之前“自然地”发生这种情况。
换句话说,是的。这将是不寻常的,但完全有可能。
【讨论】:
我知道无法以编程方式在 Unix 上设置 ctime。我不知道Windows。无论如何,您能否提供您正在考虑的 API 的参考?【参考方案4】:你搞错了!在 Linux(或 Mac,或任何其他 Unix 系统)上,ctime
通常总是晚于mtime
,而不是早于。与 Windows 不同,ctime
是文件创建日期,mtime
是文件修改日期,在 Unix 中它们是两个修改日期,不同之处在于:
mtime
会在文件 content 更改时更新
ctime
会在文件属性 更改时更新,包括其mtime
stat
utility(至少一些变体)的手册页将它们分别称为“上次数据修改时间”和“上次状态更改时间”。
因此,每当mtime
更新时,ctime
也会更新。我所知道的唯一可以让您获得大于ctime
的mtime
的机制是:
utime
or utimes
system calls 或使用touch -d
之类的实用程序手动将mtime
设置为将来
以绕过 Linux 文件系统 API 或确实完全绕过文件系统的方式写入磁盘,例如:
从 Windows 写入磁盘
opening the disk's device file and writing to it
用激光、磁铁、sonic screwdriver 或类似工具翻转磁盘上的位
既然您在 Python 的上下文中询问过,让我们制作一个简单的 Python 工具,它可以输出给定文件的 mtime
和 ctime
来帮助我们演示这一点。我们将在脚本中使用方便的os.path.getctime
和os.path.getctime
API,但使用stat
调用结果的st_ctime
和st_mtime
属性将得到完全相同的结果:
#!/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 shell 上进行实验:
$ # 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
【讨论】:
【参考方案5】:正如@ketil 所说,当文件元数据更改时,ctime 会更新。
可以改变的一种方法是,如果您将文件从一个目录移动到另一个目录。 ctime 会改变,但 mtime 不会改变。
touch test_file
mv test_file another_directory/
stat another_directory/test_file
给予
File: `another_directory/test_file'
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 80ah/2058d Inode: 23183108 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1004/ agrimm) Gid: ( 1004/ agrimm)
Access: 2011-07-07 10:11:27.000000000 +1000
Modify: 2011-07-07 10:11:27.000000000 +1000
Change: 2011-07-07 10:11:43.000000000 +1000
【讨论】:
以上是关于ctime 是不是总是 <= mtime?的主要内容,如果未能解决你的问题,请参考以下文章
Linux下find , atime, ctime,mtime