2011-01-03 7 views
6

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

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

+1

Этот вопрос был немного смущен, и его принятый ответ действительно действительно неправильный. Обычно 'mtime <= ctime', а не наоборот! См. [Мой ответ] (http://stackoverflow.com/a/39521489/1709587) для объяснения и демонстрации этого в оболочке. –

+1

'ctime' вовсе не является созданием, это метаданные ** изменить ** время. Таким образом, принятый ответ полностью и полностью ошибочен: это не просто «некоторые ситуации» или (в противном случае, как следует из этой фразы) редкие угловые случаи, когда это предположение неверно! –

ответ

4

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

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

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

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

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

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

+0

Я думаю, что вы получили это в первом предложении, верно? :-) –

+0

@ Lennart: вы правы - исправлены! :) –

+1

«некоторые ситуации» - очень, очень осторожный язык для предположения, которое не имеет существенной основы (и, как правило, * противоположно * реальной ситуации, в которой ctime> = mtime). –

3

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

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

+0

Я не знаю, как программно настроить ctime на Unix. Я не знаю о Windows. Независимо от того, не могли бы вы предоставить ссылку на API (ы), о которых вы думаете? – Nemo

4

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

ctime on 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

« меньше »всегда раньше/старше. –

0

Как сообщает @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 
1

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

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

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

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

  • установки mtime вручную, чтобы быть в будущем, используя utime or utimes system calls или утилиту, которая использует их как touch -d
  • записи на диск таким образом, чтобы в обход файловой системы Linux API, или действительно обходит файловую систему в целом, как:

Поскольку вы задали в контексте Python, давайте создадим простой инструмент Python, который выводит mtime и ctime данного файла, который поможет нам продемонстрировать это.Мы будем использовать удобные os.path.getctime и os.path.getctime API, в нашем сценарии, но с использованием st_ctime и st_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 
Смежные вопросы