Je dois trouver l'heure de création d'un fichier. Lorsque j'ai lu certains articles sur ce problème, ils ont tous indiqué qu'il n'y avait pas de solution (comme Site1 , Site2 ).
Lorsque j'ai essayé la commande stat
, elle indique Birth: -
.
Alors, comment puis-je trouver l'heure de création d'un fichier?
Il existe un moyen de connaître la date de création d'un répertoire, procédez comme suit:
Connaître l'inode du répertoire par la commande ls -i
(disons par exemple que son X)
Savoir sur quelle partition votre répertoire est enregistré à l'aide de la commande df -T /path
(disons qu'il est sur /dev/sda1
)
Maintenant, utilisez cette commande: Sudo debugfs -R 'stat <X>' /dev/sda1
Vous verrez dans la sortie:
crtime: 0x4e81cacc:966104fc -- mon Sep 27 14:38:28 2013
crtime est la date de création de votre fichier.
Ce que j'ai testé :
Modifié en créant un fichier.
J'ai essayé la commande et il a donné une heure exacte.
@Nux a trouvé ne excellente solution pour ce que vous devriez tous invoquer. J'ai décidé d'écrire une petite fonction qui peut être utilisée pour tout exécuter directement. Ajoutez simplement ceci à votre ~/.bashrc
.
get_crtime() {
for target in "${@}"; do
inode=$(stat -c '%i' "${target}")
fs=$(df --output=source "${target}" | tail -1)
crtime=$(Sudo debugfs -R 'stat <'"${inode}"'>' "${fs}" 2>/dev/null |
grep -oP 'crtime.*--\s*\K.*')
printf "%s\t%s\n" "${target}" "${crtime}"
done
}
Maintenant, vous pouvez exécuter get_crtime
pour imprimer les dates de création d’autant de fichiers ou de répertoires que vous le souhaitez:
$ get_crtime foo foo/file
foo Wed May 21 17:11:08 2014
foo/file Wed May 21 17:11:27 2014
L'incapacité de stat
à afficher l'heure de création est due à la limitation de l'appel système stat(2)
, dont la structure de retour n'incluait pas de champ pour l'heure de création. Cependant, à partir de Linux 4.11 (c'est-à-dire 17.10 et plus récent *), , le nouvel appel système statx(2)
est disponible, ce qui inclut une heure de création dans sa structure de retour.
* Et éventuellement sur des versions antérieures de LTS utilisant les noyaux de pile d’activation matérielle (HWE). Vérifiez uname -r
pour voir si vous utilisez un noyau au moins à 4.11 pour confirmer.
Malheureusement, il n'est pas facile d'appeler des appels système directement dans un programme C. Glibc fournit généralement un wrapper qui facilite la tâche, mais elle n’a ajouté un wrapper que pour statx(2)
en août 2018 (version 2.28 , disponible en 18.10). Heureusement, @whotwagner a écrit un exemple de programme C qui montre comment utiliser l'appel système statx(2)
sur des systèmes x86 et x86-64. Sa sortie est au même format que celui par défaut de stat
, sans aucune option de formatage, mais il est simple de le modifier pour n'imprimer que l'heure de la naissance.
Commencez par le cloner:
git clone https://github.com/whotwagner/statx-fun
Vous pouvez compiler le code statx.c
ou, si vous voulez seulement l'heure de naissance, créer un birth.c
dans le répertoire cloné avec le code suivant (qui est une version minimale de statx.c
n'imprimant que l'horodatage de création avec une précision à la nanoseconde):
#define _GNU_SOURCE
#define _ATFILE_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include "statx.h"
#include <time.h>
#include <getopt.h>
#include <string.h>
// does not (yet) provide a wrapper for the statx() system call
#include <sys/syscall.h>
/* this code works ony with x86 and x86_64 */
#if __x86_64__
#define __NR_statx 332
#else
#define __NR_statx 383
#endif
#define statx(a,b,c,d,e) syscall(__NR_statx,(a),(b),(c),(d),(e))
int main(int argc, char *argv[])
{
int dirfd = AT_FDCWD;
int flags = AT_SYMLINK_NOFOLLOW;
unsigned int mask = STATX_ALL;
struct statx stxbuf;
long ret = 0;
int opt = 0;
while(( opt = getopt(argc, argv, "alfd")) != -1)
{
switch(opt) {
case 'a':
flags |= AT_NO_AUTOMOUNT;
break;
case 'l':
flags &= ~AT_SYMLINK_NOFOLLOW;
break;
case 'f':
flags &= ~AT_STATX_SYNC_TYPE;
flags |= AT_STATX_FORCE_SYNC;
break;
case 'd':
flags &= ~AT_STATX_SYNC_TYPE;
flags |= AT_STATX_DONT_SYNC;
break;
default:
exit(EXIT_SUCCESS);
break;
}
}
if (optind >= argc) {
exit(EXIT_FAILURE);
}
for (; optind < argc; optind++) {
memset(&stxbuf, 0xbf, sizeof(stxbuf));
ret = statx(dirfd, argv[optind], flags, mask, &stxbuf);
if( ret < 0)
{
perror("statx");
return EXIT_FAILURE;
}
printf("%lld.%u\n", *&stxbuf.stx_btime.tv_sec, *&stxbuf.stx_btime.tv_nsec);
}
return EXIT_SUCCESS;
}
Ensuite:
$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I {} date -d @{}
Mon Nov 27 14:34:51 UTC 2017
En théorie, cela devrait rendre le temps de création plus accessible:
debugfs
est un outil destiné aux systèmes de fichiers ext2/3/4 et inutilisable sur d'autres).make
et linux-libc-dev
).Tester un système xfs, par exemple:
$ truncate -s 1G temp; mkfs -t xfs temp; mkdir foo; Sudo mount temp foo; Sudo chown $USER foo
$ touch foo/bar
$ # some time later
$ echo > foo/bar
$ chmod og-w foo/bar
$ ./birth foo/bar | xargs -I {} date -d @{}
Mon Nov 27 14:43:21 UTC 2017
$ stat foo/bar
File: foo/bar
Size: 1 Blocks: 8 IO Block: 4096 regular file
Device: 700h/1792d Inode: 99 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ muru) Gid: ( 1000/ muru)
Access: 2017-11-27 14:43:32.845579010 +0000
Modify: 2017-11-27 14:44:38.809696644 +0000
Change: 2017-11-27 14:44:45.536112317 +0000
Birth: -
Cependant, cela n'a pas fonctionné pour NTFS et exfat. Je suppose que les systèmes de fichiers Fuse pour ceux-ci n'incluaient pas le temps de création.
Si, ou plutôt quand, glibc ajoute le support pour l'appel système statx(2)
, stat
suivra bientôt et nous pourrons utiliser la vieille commande stat
en clair pour cela. Mais je ne pense pas que cela sera reporté dans les versions LTS, même s’ils obtiennent de nouveaux noyaux. Donc, je ne prévois pas stat
sur aucune des versions actuelles de LTS (14.04, 16.04 ou 18.04) pour toujours imprimer l'heure de création sans intervention manuelle.
Cependant, le 18.10, vous pouvez utiliser directement la fonction statx
comme décrit dans man 2 statx
(notez que la page de manuel 18.10 est incorrecte en indiquant que glibc n'a pas encore ajouté le wrapper).
TL; DR: Il suffit d'exécuter: Sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs>
(Pour déterminer votre fs, exécutez df -T /path/to/your/file
, ce sera très probablement /dev/sda1
).
Version longue:
Nous allons exécuter deux commandes:
Découvrez le nom du nom de la partition pour votre fichier.
df -T /path/to/your/file
La sortie va ressembler à ceci (le nom de la partition est en premier):
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/<your fs> ext4 7251432 3481272 3509836 50% /
Découvrez l'heure de création de ce fichier.
Sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs>
Dans la sortie, recherchez ctime
.