¿Ctime es siempre <= mtime?

Cuando uso os.stat () en Python, ¿puedo asumir que st_ctime siempre es menor o igual que st_mtime? ¿Si no, porque no?

El código siempre se ejecutará en Linux, pero si hay una diferencia entre los sistemas operativos, sería bueno saberlo.

Hay algunas situaciones en las que esta suposición podría resultar inválida (y dependería mucho de la implementación del SO):

  • Zonas horarias. Si crea un archivo en, digamos, UTC + 4, y luego lo modifica cuando la zona horaria actual es UTC-8, y el sistema operativo no usa UTC para todas las marcas de tiempo entre bastidores, la hora modificada será menor que el tiempo creado. Sería sorprendente que un sistema operativo moderno (Windows, OSX, uno de los BSD o Linux) tenga mtime
  • Restablecimiento de la hora del sistema operativo. Esto podría afectar el tiempo modificado para crear esta situación. Yo diría que sería mucho más probable que tuviera mtime
  • Modificando los tiempos a través de llamadas al sistema. Nuevamente, el controlador del sistema de archivos puede tener controles para evitar situaciones inusuales como esta.

Ambos son reproducibles: su mejor opción es tomar una variedad de sistemas operativos que planea orientar y probar este comportamiento. Todo lo que puedo proporcionar es especulación.

Además , st_ctime no es necesariamente el “tiempo creado”, sino el tiempo del “último cambio de estado” ( fuente ). utime marca el ctime del archivo que se actualizará ( fuente ) y su parámetro de tipo “utimbuf” no tiene ningún miembro para ctime . Por lo tanto, es técnicamente posible que ctime sea un tiempo pasado mtime si el sistema operativo y el sistema de archivos lo permiten. La documentación de os.stat realidad menciona esto:

dependiente de la plataforma hora del cambio de metadatos más reciente en Unix, o la hora de creación en Windows

Mientras Python oculta gran parte del lado C de las cosas, os.stat y sus amigos se basan en las mismas llamadas al sistema base C, por lo que la especificación para ellos es un gran lugar para buscar más información.

Es totalmente posible establecer ambos valores programáticamente. También es posible que esto suceda “naturalmente” al volver a configurar el reloj antes de crear el archivo.

En otras palabras, sí. Sería inusual pero es totalmente posible.

Por favor, defina “menos que”, ¿quiere decir más nuevo o más viejo? No puede asumir que el ctime ocurrió antes de mtime, pero normalmente ctime es lo mismo que, o después, mtime.

ctime en unix no es “crear tiempo”, sino “cambiar tiempo”. mtime se actualiza cuando se cambia el contenido de un archivo, pero ctime se actualiza cuando se cambian los metadatos del archivo (lo que significa que se actualiza cuando mtime también se actualiza), por lo que es perfectamente normal que ctime esté después de mtime. Aquí hay un ejemplo:

 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 

Además, creo que en Windows, el campo ctime en realidad significa “crear tiempo”, y que esta es una diferencia de sistema operativo entre Windows y Unix. He leído algo sobre esto en línea, pero te dejaré hacer tu propia investigación sobre esto.

¡Te has equivocado de camino! En Linux (o Mac, o cualquier otro sistema Unix), ctime normalmente siempre será MÁS TARDE que mtime , no antes. A diferencia de Windows, donde ctime es una fecha de creación de archivo y mtime es una fecha de modificación de archivo, en Unix ambas son fechas de modificación, con la diferencia de que:

  • mtime se actualiza cada vez que cambia el contenido del archivo
  • ctime se actualiza cada vez que cambian los atributos del archivo, incluido su mtime

La página del manual para (al menos algunas variantes de) la utilidad de stat refiere a estos respectivamente como “Tiempo de la última modificación de datos” y “Tiempo de último cambio de estado” .

Así, cada vez que mtime se actualiza, ctime también se actualiza. Los únicos mecanismos que conozco para poder obtener un mtime mayor que el ctime son:

  • configurando manualmente el mtime para que sea en el futuro usando las llamadas del sistema utime o utimes , o una utilidad que las use como touch -d
  • escribir en el disco de una manera que omita la API del sistema de archivos de Linux, o incluso omita el sistema de archivos por completo, como:
    • escribiendo en el disco desde Windows
    • abriendo el archivo del dispositivo del disco y escribiéndolo
    • Cambio de bits en el disco con un láser, un imán, un destornillador sónico o similar

Ya que ha preguntado en el contexto de Python, hagamos una herramienta Python simple que mtime y ctime de un archivo dado para ayudarnos a demostrar esto. Usaremos las convenientes API os.path.getctime y os.path.getctime en nuestro script, pero usar las propiedades st_ctime y st_mtime del resultado de una llamada a stat daría exactamente los mismos resultados:

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

Podemos guardar eso como pystat.py , hacerlo ejecutable y experimentar en nuestro shell de 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 

Como dice @ketil, ctime se actualiza cuando se cambian los metadatos del archivo.

Una forma en que esto puede cambiar es que si mueve un archivo de un directorio a otro. ctime cambiará, pero no mtime.

 touch test_file mv test_file another_directory/ stat another_directory/test_file 

da

  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