When using os.stat() in Python, can I assume that st_ctime is always less then or equal to st_mtime? If not, why not?
The code will always run on Linux, but if there is
You've got this the wrong way round! On Linux (or Mac, or any other Unix system), ctime
will normally always be LATER than mtime
, not earlier. Unlike Windows, where ctime
is a file creation date and mtime
is a file modification date, in Unix they're both modification dates, with the difference being that:
mtime
gets updated whenever the file content changesctime
gets updated whenever the file attributes change, including its mtime
The man page for (at least some variants of) the stat utility refers to these respectively as the "Time of last data modification" and "Time of last status change".
Thus whenever mtime
gets updated, ctime
also gets updated. The only mechanisms I know of by which you could ever get an mtime
that is greater than the ctime
are:
mtime
to be in the future using the utime or utimes system calls, or a utility that uses them like touch -dSince you've asked in the context of Python, let's make a simple Python tool that outputs the mtime
and ctime
of a given file to help us demonstrate this. We'll use the convenient os.path.getctime and os.path.getctime APIs in our script, but using the st_ctime
and st_mtime
properties of the result of a stat call would give exactly the same results:
#!/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))
We can save that as pystat.py
, make it executable, and experiment at our 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