Как я нахожу время создания файла?

Я должен найти время создания файла, когда я прочитал некоторые статьи об этой проблеме, все упомянули, что нет никакого решения (как Site1, Site2).

Когда я попробовал stat команда, указывает это Birth: -.

Таким образом, как я могу найти время создания файла?

82
задан 27 November 2017 в 08:35

5 ответов

Есть способ узнать дату создания каталога, просто выполните следующие действия:

  1. Узнайте inode каталога с помощью ls -i команда (скажем, ее X )

  2. Узнайте, на каком разделе сохранен ваш каталог, с помощью команды df -T / path (скажем, это на / dev / sda1 )

  3. Теперь используйте эту команду: sudo debugfs -R 'stat ' / dev / sda1

В выводе вы увидите:

crtime: 0x4e81cacc:966104fc -- mon Sep 27 14:38:28 2013

crtime - дата создания вашего файла.

Что я тестировал :

  1. Создал каталог в определенное время.
  2. Получил доступ к нему.
  3. Изменил его, создав файл.

  4. Я попробовал команда, и она дала точное время.

  5. Затем я изменяю ее и снова проверяю, crtime осталось прежним, но изменить и доступ время изменено.
71
ответ дан 22 November 2019 в 23:33

@Nux нашел отличное решение для этого, которое вы все должны проголосовать. Я решил написать небольшую функцию, которую можно было бы использовать для прямого запуска всего. Просто добавьте это в свой ~ / .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
}

Теперь вы можете запустить get_crtime , чтобы распечатать даты создания любого количества файлов или каталогов:

$ get_crtime foo foo/file 
foo Wed May 21 17:11:08 2014
foo/file    Wed May 21 17:11:27 2014
60
ответ дан 22 November 2019 в 23:33

TL; DR: Просто беги: sudo debugfs -R 'stat / path / to / your / file' / dev /

(Чтобы определить вашу fs, запустите df -T / path / to / your / file , скорее всего, это будет / dev / sda1 ).

Длинная версия:

Мы собираемся запустить две команды:

  1. Узнать имя раздела для ваш файл.

     df -T / путь / к / вашему / файлу
     

    Вывод будет выглядеть следующим образом (сначала имя раздела):

     Тип файловой системы Используется 1K-блоков Доступно Использовано% Установлено на
     / dev / <ваша фс> ext4 7251432 3481272 3509836 50% /
     
  2. Узнать время создания этого файла.

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

    В выходных данных найдите ctime .

3
ответ дан 22 November 2019 в 23:33

Неспособность stat показать время создания связана с ограничением системного вызова stat (2) , структура возврата которого не включает поле для времени создания. Однако, начиная с Linux 4.11 (т.е. 17.10 и новее *), доступен новый системный вызов statx (2) , который включает время создания в его возвращаемую структуру.

* И, возможно, в более старых версиях LTS, использующих ядра аппаратного стека (HWE). Проверьте uname -r , чтобы убедиться, что вы используете ядро ​​версии не ниже 4.11 для подтверждения.

К сожалению, вызывать системные вызовы непосредственно в программе на языке C непросто. Обычно glibc предоставляет оболочку, которая упрощает работу, но glibc добавила оболочку только для statx (2) в августе 2018 г. (версия 2.28 , доступна в 18.10). Сама команда stat получила поддержку statx (2) только в GNU coreutils 8.31 (выпущена в марте 2019 г.) , однако даже только Ubuntu 20.04 имеет coreutils 8.30 .

Но я не думаю, что это будет перенесено на выпуски LTS, даже если они получат или уже используют новые ядра или glibcs. Поэтому я не ожидаю, что stat в любой текущей версии LTS (16.04, 18.04 или 20.04) когда-либо напечатает время создания без ручного вмешательства.

В 18.10 и новее, вы можете напрямую использовать функцию statx , как описано в man 2 statx (обратите внимание, что на странице руководства 18.10 неверно указано, что glibc еще не добавил оболочку).

в Ubuntu 20.10 вы сможете использовать stat напрямую:

# 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

К счастью, для старых систем @whotwagner написал пример программы на C , в которой показано, как использовать Системный вызов statx (2) в системах x86 и x86-64. Его вывод имеет тот же формат, что и stat по умолчанию, без каких-либо параметров форматирования, но его просто изменить, чтобы печатать только время рождения.

Сначала клонируйте его:

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

Вы можете скомпилировать код statx.c или, если вам просто нужно время рождения, создайте Birth.c в клонированном каталоге со следующим кодом (который является минимальной версией ] statx.c печатает только временную метку создания, включая точность наносекунды):

#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;
}

Затем:

$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I {} date -d @{}
Mon Nov 27 14:34:51 UTC 2017

Теоретически это должно сделать время создания более доступным:

  • должно поддерживаться больше файловых систем, чем только ext * ( debugfs - это инструмент для файловых систем ext2 / 3/4, который нельзя использовать в других)
  • вам не нужен root, чтобы использовать это (за исключением установки некоторых необходимых пакетов, таких как make и linux-libc-dev ).

Тестирование системы xfs, например:

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

Однако это не сработало для NTFS и exfat. Я полагаю, что файловые системы FUSE для них не учитывали время создания.

15
ответ дан 22 November 2019 в 23:33

Моя ОС (Ubuntu 20.04, которая поставляется с ядром Linux 5.4.0-28 и GLIBC 2.31) поставлялась только с GNU coreutils 8.30, поэтому мне пришлось заставить ее работать, скомпилировав GNU coreutils версии 8.32 из исходников . Это была относительно безболезненная процедура.

После этого и ls , и stat могли работать со временем рождения.

Вывод ls -l --time = рождение --time-style = full-iso --no-group : ls with birth time

Вывод stat в файловой системе ext4 и файловой системе btrfs: stat with birth time

(Скопировано из моего другого ответа на UNIX и Linux Stack Exchange )

1
ответ дан 5 January 2021 в 23:07

Другие вопросы по тегам:

Похожие вопросы: