2011-01-03 11 views
6

Podczas korzystania z os.stat() w Pythonie, czy mogę założyć, że st_ctime jest zawsze mniejsze lub równe st_mtime? Jeśli nie, dlaczego nie?Czy ctime jest zawsze <= mtime?

Kod zawsze będzie działał w systemie Linux, ale jeśli istnieje różnica między systemami, dobrze byłoby wiedzieć.

+1

To pytanie było nieco zagmatwane, a jego zaakceptowana odpowiedź jest naprawdę zła. Zwykle 'mtime <= ctime', a nie na odwrót! Zobacz [moja odpowiedź] (http://stackoverflow.com/a/39521489/1709587) dla wyjaśnienia i demonstracji tego w powłoce. –

+1

'ctime' to wcale nie jest tworzenie, to metadane ** zmieniają ** czas. Przyjęta odpowiedź jest zatem całkowicie i całkowicie błędna: nie chodzi tylko o "pewne sytuacje" lub (inaczej, jak to to oznacza) rzadkich przypadków narożnych, w których to założenie jest nieważne! –

Odpowiedz

4

Istnieją pewne sytuacje, w których założenie to mogłoby okazać się nieważne (i będzie zależeć w dużej mierze od realizacji OS):

  • Okna czasowe. Jeśli utworzysz plik w, powiedzmy, UTC + 4, a następnie zmodyfikuj go, gdy aktualna strefa czasowa jest UTC-8, a system operacyjny nie użyje UTC dla wszystkich znaczników czasowych za kulisami, zmodyfikowany czas będzie mniejszy niż stworzony czas. Byłoby zaskakujące, gdyby w tym przypadku nowoczesny system operacyjny (Windows, OSX, jeden z BSD lub Linux) miał mtime < ctime.
  • Resetowanie czasu systemu operacyjnego. Może to wpłynąć na zmodyfikowany czas utworzenia tej sytuacji. Powiedziałbym, że byłoby znacznie bardziej prawdopodobne, że będziesz miał czas na mtime < ctime bez skarg ze strony systemu operacyjnego w tym przypadku, zakładając, że nie ma kontroli w systemie plików, aby tego uniknąć.
  • Modyfikowanie czasów poprzez wywołania systemowe. Ponownie, sterownik systemu plików może mieć kontrole w celu uniknięcia nietypowych sytuacji, takich jak ta.

Oba są odtwarzalne: najlepiej jest wziąć różne systemy operacyjne, które planujesz ukierunkować i przetestować to zachowanie. Wszystko, co mogę zapewnić, to spekulacja.

Również, st_ctime niekoniecznie jest "czasem stworzonym", ale raczej czasem "ostatniej zmiany statusu" (source). utime oznacza ctime pliku do zaktualizowania (source), a jego parametr typu "utimbuf" nie ma elementu dla ctime. Jest więc technicznie możliwe, że ctime będzie czasem minionym, jeśli system operacyjny i system plików na to pozwolą. Dokumentacja os.stat w rzeczywistości wspomina o tym:

zależna od platformy; czas najbardziej niedawnej zmiany metadanych Unix lub czasu stworzenia na Windows

Podczas Pythonie ukrywa wiele boku C rzeczy os.stat i wszyscy przyjaciele są zbudowane na tym samym systemie baza C wywołuje tak specyfikacja dla nich jest doskonałym miejscem do wyszukiwania dodatkowych informacji.

+0

Myślę, że masz go w pierwszym zdaniu, prawda? :-) –

+0

@ Lennart: masz rację - naprawiono! :) –

+1

"Niektóre sytuacje" są bardzo, bardzo ostrożnym językiem dla założenia, które nie ma znaczącej podstawy (i ogólnie jest * przeciwieństwem * faktycznej sytuacji, w której ctime> = mtime). –

3

Całkowicie można ustawić obie wartości programowo. Możliwe, że stanie się to "naturalnie", ustawiając zegar z powrotem przed utworzeniem pliku.

Innymi słowy, tak. Byłoby to niezwykłe, ale całkowicie możliwe.

+0

Nie wiem, w jaki sposób programowo ustawić ctime na Unix. Nie wiem o Windows. Niezależnie od tego, czy mógłbyś podać odniesienie do API, o którym myślisz? – Nemo

4

Proszę zdefiniować "mniej niż", masz na myśli nowsze lub starsze? Nie można założyć, że ctime wydarzyło się przed mtime, ale zwykle ctime jest takie samo jak po mtime.

ctime na unixie nie jest "stworzyć czas", ale "zmienić czas". mtime jest aktualizowane, gdy zmienia się zawartość pliku, ale ctime jest aktualizowane, gdy metadane pliku są zmieniane (co oznacza, że ​​są aktualizowane, gdy mtime również jest aktualizowane), więc normalne jest, że ctime będzie po mtime.Oto przykład:

[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 

Również uważam, że w systemie Windows, w polu ctime właściwie znaczy „tworzyć czas”, i że jest to różnica pomiędzy OS Windows i Unix. Czytałem coś o tym w Internecie, ale pozwolę ci zrobić własne badania na ten temat.

+3

"mniej niż" jest zawsze przed/starsze. –

0

Jak mówi @ketil, ctime jest aktualizowane po zmianie metadanych pliku.

Jednym ze sposobów zmiany tej opcji jest przeniesienie pliku z jednego katalogu do drugiego. ctime się zmieni, ale nie mtime.

touch test_file 
mv test_file another_directory/ 
stat another_directory/test_file 

daje

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

Masz to w niewłaściwy sposób okrągłe! W systemie Linux (lub Mac, lub w dowolnym innym systemie uniksowym), ctime będzie zwykle zawsze PÓŹNIEJSZY niż mtime, nie wcześniej. W przeciwieństwie do Windows, gdzie ctime jest data utworzenia pliku i mtime jest data modyfikacji pliku w systemie Unix oni oba daty modyfikacji, z tą różnicą, że:

  • mtime zostanie zaktualizowany, gdy plik zawartość zmienia
  • ctime zostanie zaktualizowany, gdy plik atrybuty zmiany, łącznie z jego mtime

Strona podręcznika dla (przynajmniej niektórych wariantów) stat utility odnosi się do nich odpowiednio jako "Czas ostatniej modyfikacji danych" i "Czas ostatniej zmiany statusu".

Tak więc zawsze, gdy mtime zostanie zaktualizowany, ctime również zostanie zaktualizowany. Jedynymi mechanizmy znam, w którym można zawsze uzyskać mtime, która jest większa niż ctime są:

Skoro już zadawane w kontekście Pythonie, zróbmy proste narzędzie Pythona, który wyprowadza mtime i ctime danego pliku, aby pomóc nam to zademonstrować.Będziemy korzystać z dogodnych os.path.getctime i os.path.getctime API w skrypcie, ale stosując st_ctime i st_mtime właściwości wyniku stat rozmowy dałby dokładnie takie same wyniki:

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

możemy zaoszczędzić że pystat.py, zrobić jest to plik wykonywalny i eksperyment w naszej powłoce Uniksa:

$ # 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