Всегда ли ctime <= mtime?

При использовании os.stat() в Python, могу ли я предположить, что st_ctime всегда меньше или равно st_mtime? Если нет, почему бы и нет?

Код всегда будет работать в Linux, но если есть разница между ОС, это было бы полезно знать.

Ответ 1

Есть ситуации, когда это предположение может оказаться недействительным (и будет сильно зависеть от реализации ОС):

  • Часовые пояса. Если вы создаете файл, например, UTC + 4, а затем изменяете его, когда текущий часовой пояс UTC-8, а операционная система не использует UTC для всех временных задержек, измененное время будет меньше чем созданное время. Было бы удивительно, если бы современная операционная система (Windows, OSX, одна из BSD или Linux) имела mtime < ctime в этом случае.
  • Сброс времени работы ОС. Это может повлиять на измененное время, чтобы создать эту ситуацию. Я бы сказал, что было бы гораздо более вероятно, что у вас будет mtime < ctime без жалобы от ОС в этом случае, если в драйвере файловой системы нет проверок, чтобы избежать этого случая.
  • Изменение времени через системные вызовы. Опять же, драйвер файловой системы может иметь проверки, чтобы избежать таких необычных ситуаций, как это.

Оба из них воспроизводимы: лучше всего принять различные операционные системы, которые вы планируете настроить и проверить это поведение. Все, что я могу предоставить, - это спекуляция.

Кроме того,, st_ctime не обязательно является "созданным временем", а скорее временем "последнего изменения статуса" (source). utime помещает ctime файла, который будет обновляться (источник), а параметр типа "utimbuf" не имеет члена для ctime. Поэтому технически возможно, что ctime будет временем mtime, если это разрешит операционная система и файловая система. Документация os.stat фактически упоминает это:

зависит от платформы; времени большинства недавние изменения метаданных в Unix, или время создания в Windows

В то время как Python скрывает много сторонности C, os.stat и все друзья построены на тех же базовых системах C, поэтому спецификация для них - отличное место для поиска дополнительной информации.

Ответ 2

Пожалуйста, определите "меньше", вы имеете в виду более новые или более старые? Вы не можете предположить, что ctime произошел до mtime, но обычно ctime совпадает с mtime или после него.

ctime в unix не "создает время", а "изменить время". mtime обновляется при изменении содержимого файла, но ctime обновляется при изменении метаданных файла (что означает, что он обновляется, когда mtime также обновляется), поэтому совершенно нормально для ctime быть после mtime. Вот пример:

[email protected]:~$ touch test
[email protected]:~$ chmod 600 test
[email protected]:~$ 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. Я читал что-то об этом в Интернете, но я позволю вам сделать это самостоятельно.

Ответ 3

Полностью можно установить оба значения программно. Возможно, вы также сможете добиться этого "естественно", установив часы назад до создания файла.

Иными словами, да. Это было бы необычно, но вполне возможно.

Ответ 4

У тебя это не так! В Linux (или Mac или любой другой системе Unix) ctime обычно будет LATER, чем mtime, а не раньше. В отличие от Windows, где ctime - дата создания файла, а mtime - дата изменения файла, в Unix они оба являются датами изменения, с той разницей, что:

  • mtime обновляется всякий раз, когда изменяется содержимое файла.
  • ctime обновляется всякий раз, когда изменяются атрибуты файла, включая mtime

Страница руководства для (по крайней мере, некоторых вариантов) stat utility относится к ним соответственно как "Время последних данных изменение" и "Время последнего изменения статуса".

Таким образом, всякий раз, когда mtime обновляется, ctime также обновляется. Единственными механизмами, которые я знаю, с которыми вы могли бы получить mtime, который больше, чем ctime, являются:

Так как вы спросили в контексте Python, сделайте простой инструмент Python, который выводит mtime и ctime данного файла, чтобы помочь нам продемонстрировать это. Мы будем использовать удобный os.path.getctime и os.path.getctime в нашем script, но используя свойства st_ctime и st_mtime результата stat call даст точно такие же результаты:

#!/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

Ответ 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