¿Cómo encontrar la fecha de creación del archivo?

104

Quiero averiguar la fecha de creación de un archivo en particular, no la fecha de modificación o la fecha de acceso.

He intentado con ls -ltrhy stat filename.

Özzesh
fuente
55
Linux no realiza un seguimiento del tiempo de creación, ya que POSIX no lo requiere. Sin embargo, Mac OS X lo hace con el sistema de archivos HFS: busque en "hora de nacimiento" en stat(1).
200_success
2
Los sistemas de archivos Fedora 19 ext4 establecen tiempos de creación de archivos. Estoy seguro de que hay muchos más ejemplos. Vea la respuesta a continuación que se utiliza stappara recuperar los tiempos de creación.
rickhg12hs

Respuestas:

88

El estándar POSIX solo define tres marcas de tiempo distintas que se almacenarán para cada archivo: la hora del último acceso a datos, la hora de la última modificación de datos y la hora en que el estado del archivo cambió por última vez.

Dicho esto, los sistemas de archivos modernos de Linux, como ext4, Btrfs y JFS, almacenan el tiempo de creación del archivo (también conocido como hora de nacimiento), pero usan diferentes nombres para el campo en cuestión ( crtimeen ext4, otimeen Btrfs y JFS). Sin embargo, actualmente Linux no proporciona una API de kernel para acceder a los tiempos de creación de archivos , incluso en los sistemas de archivos que los admiten.

Como Craig Sanders y Mohsen Pahlevanzadeh señalaron, statno apoyar el %wy %Wespecificadores de formato de visualización de la hora del archivo a luz (en formato legible por humanos y en segundos desde el Epoch respectivamente). Sin embargo, stataccede al tiempo de nacimiento a través del get_stat_birthtime()proporcionado por gnulib (in lib/stat-time.h), que obtiene el tiempo de nacimiento de los campos st_birthtimey st_birthtimensecde la statestructura devueltos por la stat()llamada al sistema. Mientras que, por ejemplo, los sistemas BSD (y en la extensión OS X) proporcionan st_birthtimevía stat, Linux no. Esta es la razón por la cual las stat -c '%w' filesalidas -(que indican un tiempo de creación desconocido) en Linux incluso para sistemas de archivos que almacenan el tiempo de creación internamente.

Como señala Stephane Chazelas , algunos sistemas de archivos, como ntfs-3g, exponen los tiempos de creación de archivos a través de atributos de archivo extendidos.

Thomas Nyman
fuente
44
En Linux, ahora se almacena en muchos sistemas de archivos, incluido ext4. Sin embargo, todavía no hay una API de kernel para obtenerlo. Algunos sistemas de archivos como ntfs-3g sobre fusible lo hacen disponible a través de la API de atributos extendidos
Stéphane Chazelas
@StephaneChazelas Gracias por sus comentarios. Se actualizó la respuesta para proporcionar más detalles.
Thomas Nyman
Puede usar stappara crear su propia API de kernel. Ver ejemplo en respuesta aquí.
rickhg12hs
26

TLDR; Use stap( "SystemTap" ) para crear su propia API de kernel. Demostración de la extracción del tiempo de creación ext4 a continuación.

Puede extraer los tiempos de creación de ext4 en los sistemas Fedora 19. Aquí está el mío:

$ uname -a
Linux steelers.net 3.11.1-200.fc19.i686.PAE #1 SMP Sat Sep 14 15:20:42 UTC 2013 i686 i686 i386 GNU/Linux

Está claro que los inodes en mis particiones ext4 tienen el tiempo de creación. Aquí hay un script de shell que determina el inodo asociado con un nombre de archivo y luego aumenta la statsalida con el tiempo de creación usando stap("systemtap").

NB: Esto es solo una demostración y enormemente ineficiente ya que se crea, carga y descarga un módulo de kernel para cada ejecución. Esto también es probablemente muy frágil ya que no se realiza ninguna comprobación de errores. Sería preferible una API de kernel adecuada, pero este script podría hacerse mucho más eficiente y leer los tiempos de creación de múltiples archivos / inodos.

[contenido de stap_stat.sh]

#/bin/sh

my_inode_str=$(stat --printf="%i" $1)

stap - << end_of_stap_script
global my_offsetof
probe begin {
  system("stat $1");
  my_offsetof = &@cast(0,"struct ext4_inode_info")->vfs_inode;
}
probe kernel.function("ext4_getattr@fs/ext4/inode.c") {
  probe_inode=\$dentry->d_inode;
  if (@cast(probe_inode, "struct inode")->i_ino == $my_inode_str) {
    my_i_crtime = &@cast(probe_inode - my_offsetof,"struct ext4_inode_info")->i_crtime;
    printf("CrTime: %s GMT\n", ctime(@cast(my_i_crtime, "timespec")->tv_sec));
    printf("CrTime (nsecs): %d\n", @cast(my_i_crtime, "timespec")->tv_nsec);
    exit();
  }
}
end_of_stap_script

Aquí hay una demostración:

$ ll testfile
ls: cannot access testfile: No such file or directory
$ touch testfile
$ ./stap_stat.sh testfile
  File: ‘testfile’
  Size: 0           Blocks: 0          IO Block: 4096   regular empty file
Device: fd02h/64770d    Inode: 4850501     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1001/    Rick)   Gid: ( 1001/    Rick)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2013-09-28 06:17:04.221441084 -0400
Modify: 2013-09-28 06:17:04.221441084 -0400
Change: 2013-09-28 06:17:04.221441084 -0400
 Birth: -
CrTime: Sat Sep 28 10:17:04 2013 GMT
CrTime (nsecs): 220441085
$ ll testfile
-rw-rw-r--. 1 Rick Rick 0 Sep 28 06:17 testfile
$ cat - >> testfile 
Now is the time ...
$ ll testfile 
-rw-rw-r--. 1 Rick Rick 20 Sep 28 06:18 testfile
$ ./stap_stat.sh testfile
  File: ‘testfile’
Device: fd02h/64770d    Inode: 4850501     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1001/    Rick)   Gid: ( 1001/    Rick)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2013-09-28 06:17:04.221441084 -0400
Modify: 2013-09-28 06:18:33.684374740 -0400
Change: 2013-09-28 06:18:33.684374740 -0400
 Birth: -
CrTime: Sat Sep 28 10:17:04 2013 GMT
CrTime (nsecs): 220441085
$ cat testfile 
Now is the time ...
$ ./stap_stat.sh testfile
  File: ‘testfile’
  Size: 20          Blocks: 8          IO Block: 4096   regular file
Device: fd02h/64770d    Inode: 4850501     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1001/    Rick)   Gid: ( 1001/    Rick)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2013-09-28 06:19:12.199349463 -0400
Modify: 2013-09-28 06:18:33.684374740 -0400
Change: 2013-09-28 06:18:33.684374740 -0400
 Birth: -
CrTime: Sat Sep 28 10:17:04 2013 GMT
CrTime (nsecs): 220441085
$ mv testfile testfile2
$ ./stap_stat.sh testfile2 
  File: ‘testfile2’
  Size: 20          Blocks: 8          IO Block: 4096   regular file
Device: fd02h/64770d    Inode: 4850501     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1001/    Rick)   Gid: ( 1001/    Rick)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2013-09-28 06:19:12.199349463 -0400
Modify: 2013-09-28 06:18:33.684374740 -0400
Change: 2013-09-28 06:20:45.870295668 -0400
 Birth: -
CrTime: Sat Sep 28 10:17:04 2013 GMT
CrTime (nsecs): 220441085
$ 
rickhg12hs
fuente
44
Ok, eso es genial. +1 por usar stap, mono parcheando el kernel de linux, increíble.
Chris Magnuson
@ChrisMagnuson: debugfs + statpermite obtener crtimesin mono parchear el núcleo.
jfs
17

En ext4esto es posible; porque ext4el sistema de archivos almacena el tiempo de creación del archivo. Pero aún así, encontrará que el statcomando no puede mostrar la fecha, porque creo que el núcleo no tiene ninguna API para esto.

De todos modos, el tiempo de nacimiento del archivo está almacenado ext4y puede averiguarlo, aunque no por un método directo, sino utilizandodebugfs

sudo debugfs -R "stat / ABSOLUTE / PATH" / dev / sdxX | grep crtime

principiante
fuente
1
como una función bash:xstat filename
jfs
1
Si /dev/sdxXestá montado /some/pathy el archivo está /some/path/some/file, la ruta a especificar es solo some/file: su ruta debe referirse no a la raíz del sistema de archivos, sino al punto de montaje. De lo contrario, no se encontrará el archivo.
BowPark
15

En teoría, con GNU stat podría usar stat -c '%w'o %Wpara obtener la fecha de creación de un archivo (también conocido como hora de nacimiento).

En la práctica, la mayoría de los sistemas de archivos no registran esa información y el kernel de Linux no proporciona ninguna forma de acceder a ella.

Lo más cercano que puede obtener es el ctime del archivo, que no es el tiempo de creación, es el momento en que los metadatos del archivo se modificaron por última vez.

Linux Weekly News tuvo un interesante artículo sobre esto hace unos años: http://lwn.net/Articles/397442/

cas
fuente
7
stat --printf='%w' yourfile   #human readable

stat --printf='%W' yourfile   #seconds from Epoch , 0 if unknown

Diferencia entre FreeBSDy GNU\Linuxsobre stat command:

Si llama al statcomando GNU\Linux, invoca la -x opción, pero en FreeBSD, usted mismo debería invocar la -xopción.

Consulte también ¿Qué sistemas de archivos en Linux almacenan el tiempo de creación?

Notas: --printf es muy útil en scripting....!

Golfo pérsico
fuente
//, probé esto en una máquina CEntOS 6, y todo lo que obtuve fueron signos de interrogación: $ stat --printf = '% w' ~ / dump.rdb? Tal vez mi sistema de archivos no admite estadísticas con% w.
Nathan Basanese
desafortunadamente, HFS no admite ctime.
PersianGulf
5

En OS X puede utilizar ls -lU, stat -f%B, GetFileInfo -d, o mdls -n kMDItemFSCreationDate:

$ ls -lU
total 0
-rw-r--r--  1 lauri  staff  0 Apr 25 03:58 a
$ stat -f%B a
1398387538
$ stat -f%SB -t %Y%m%d%H%M a
201404250358
$ GetFileInfo -d a
04/25/2014 03:58:58
$ mdls -n kMDItemFSCreationDate a
kMDItemFSCreationDate = 2014-04-25 00:58:58 +0000
Lri
fuente
2

Mira esto:

# the last arg is the device to scan in.
debugfs -R 'stat /home/renich/somefile' /dev/sda1

Por cierto, esto funciona solo en ext4. No he encontrado una solución para BtrFS ... todavía;)

Renich
fuente
1
Eso es más o menos lo que dice la respuesta del principiante ... ¿no?
don_crissti
whoops, tienes razón @don_crissti
Renich