84 votes

Comment trouver l'heure de création d'un fichier ?

J'ai besoin de trouver l'heure de création d'un fichier. Lorsque j'ai lu quelques articles sur ce sujet, tous ont mentionné qu'il n'y avait pas de solution (comme par ex. Site1 , Site2 ).

Quand j'ai essayé le stat il est indiqué Birth: - .

Alors comment puis-je trouver l'heure de création d'un fichier ?

76voto

nux Points 34943

Il existe un moyen de connaître la date de création d'un répertoire, il suffit de suivre les étapes suivantes :

  1. Connaître le inode du répertoire par ls -i (disons par exemple que la commande X )

  2. Savoir sur quelle partition votre répertoire est sauvegardé df -T /path (disons que c'est sur /dev/sda1 )

  3. Utilisez maintenant 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é :

  1. Création d'un répertoire à un moment précis .

  2. Accédez-y .

  3. Modifié en créant un fichier .

  4. J'ai essayé la commande et cela a donné une heure exacte.

  5. Ensuite, je le modifie, et je teste à nouveau, le résultat est le même. crtime est resté le même, mais modifier y accès changement d'heure .

65voto

Stewart Points 1385

@Nux a trouvé une excellente solution pour ça, que vous devriez tous upvoter. J'ai décidé d'écrire une petite fonction qui peut être utilisée pour tout lancer 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

19voto

muru Points 180007

L'incapacité de stat pour montrer que le temps de création est dû à la limitation de la stat(2) appel système dont la structure de retour ne comprend pas de champ pour le temps de création. À partir de Linux 4.11 (c'est-à-dire 17.10 et plus récents*), cependant, le nouveau statx(2) appel système est disponible, qui inclut un temps de création dans sa structure de retour.

* Et éventuellement sur les anciennes versions LTS utilisant les noyaux HWE (Hardware enablement stack). Consultez <code>uname -r</code> pour voir si vous utilisez un noyau au moins à 4.11 pour confirmer.

Malheureusement, il n'est pas facile d'appeler les appels système directement dans un programme C. En général, la glibc fournit un wrapper qui facilite le travail, mais la glibc n'a ajouté qu'un wrapper pour statx(2) en août 2018 (version 2.28 disponible en 18.10). Le site stat Le commandement lui-même a obtenu le soutien de statx(2) uniquement dans GNU coreutils 8.31 (publié en mars 2019) Cependant, même Ubuntu 20.04 ne dispose que de coreutils 8.30 .

Mais je ne pense pas que cela sera reporté sur les versions LTS même si elles obtiennent, ou sont déjà sur, des noyaux ou des glibcs plus récents. Donc, je ne m'attends pas à ce que stat sur toute version LTS actuelle (16.04, 18.04 ou 20.04) pour toujours imprimer l'heure de création sans intervention manuelle.

Sous la version 18.10 et les versions plus récentes, vous pouvez utiliser directement la commande statx comme décrit dans man 2 statx (notez que la page de manuel de la version 18.10 est incorrecte en affirmant que la glibc n'a pas encore ajouté le wrapper).

Et dans Ubuntu 20.10, vous pourrez utiliser stat directement :

# stat --version
stat (GNU coreutils) 8.32
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Michael Meskes.
# stat /
  File: /
  Size: 4096        Blocks: 8          IO Block: 4096   directory
Device: 88h/136d    Inode: 57279593    Links: 1
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2020-08-18 06:57:46.912243164 +0000
Modify: 2020-08-18 06:57:06.768492334 +0000
Change: 2020-08-18 06:57:59.136165661 +0000
 Birth: 2020-08-18 06:57:06.768492334 +0000

Pour les systèmes plus anciens, heureusement, @whotwagner a écrit un exemple de programme C qui montre comment utiliser le statx(2) sur les systèmes x86 et x86-64. Sa sortie a le même format que stat L'heure de naissance est la valeur par défaut, sans aucune option de formatage, mais il est facile de la modifier pour n'imprimer que l'heure de naissance.

D'abord, clonez-le :

git clone https://github.com/whotwagner/statx-fun

Vous pouvez compiler le statx.c ou, si vous souhaitez uniquement connaître l'heure de naissance, créez un code birth.c dans le répertoire cloné avec le code suivant (qui est une version minimale de statx.c en imprimant uniquement l'horodatage de création, avec une précision de l'ordre de 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;
}

Entonces:

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

  • plus de systèmes de fichiers devraient être supportés que les seuls ext* ( debugfs est un outil pour les systèmes de fichiers ext2/3/4, et inutilisable sur les autres)
  • vous n'avez pas besoin de root pour l'utiliser (sauf pour installer certains paquets nécessaires, comme make y 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'incluent pas le temps de création.

6voto

fsonmezay Points 323

TL;DR : Cours juste : sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs>

(Pour connaître votre fs, exécutez df -T /path/to/your/file le plus souvent, ce sera /dev/sda1 ).

Version longue :

Nous allons exécuter deux commandes :

  1. Trouvez le nom de la partition de 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% /
  2. Trouvez l'heure de création de ce fichier.

    sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs>

    Dans le résultat, recherchez ctime .

3voto

IamSk Points 21

Mon système d'exploitation (Ubuntu 20.04, qui est livré avec le noyau Linux 5.4.0-28 et GLIBC 2.31) n'est livré qu'avec GNU coreutils 8.30, j'ai donc dû le faire fonctionner en compilation de la version 8.32 de GNU coreutils à partir des sources . C'était une procédure relativement indolore.

Ensuite, les deux ls y stat pourrait travailler avec l'heure de naissance.

Sortie de ls -l --time=birth --time-style=full-iso --no-group : ls with birth time

Sortie de stat sur un système de fichiers ext4 et un système de fichiers btrfs : stat with birth time

(Copié de mon autre réponse sur UNIX & Linux Stack Exchange )

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X