Дата рождения файла [dубликат]

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

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

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

51
задан 27 November 2017 в 19:35

8 ответов

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

Знайте индексный дескриптор каталога командой ls -i (скажем, например, его X). Знайте, на каком перейдите в раздел df -T /path). Теперь используйте эту команду: sudo debugfs -R 'stat <X>' /dev/sda1

Вы увидите на выходе:

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

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

crtime :

Знать inode каталога с помощью команды ls -i (скажем, например, его X) Доступ к нему. Знайте, на каком разделе ваш каталог будет сохранен командой df -T /path (скажем, на /dev/sda1)

Знайте, на каком разделе ваш каталог будет сохранен командой df -T /path (скажем, его /dev/sda1)

Теперь используйте эту команду: sudo debugfs -R 'stat <X>' /dev/sda1
55
ответ дан 18 July 2018 в 03:23

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

Знайте индексный дескриптор каталога командой ls -i (скажем, например, его X). Знайте, на каком перейдите в раздел df -T /path). Теперь используйте эту команду: sudo debugfs -R 'stat <X>' /dev/sda1

Вы увидите на выходе:

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

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

crtime :

Знать inode каталога с помощью команды ls -i (скажем, например, его X) Доступ к нему. Знайте, на каком разделе ваш каталог будет сохранен командой df -T /path (скажем, на /dev/sda1)

Знайте, на каком разделе ваш каталог будет сохранен командой df -T /path (скажем, его /dev/sda1)

Теперь используйте эту команду: sudo debugfs -R 'stat <X>' /dev/sda1
55
ответ дан 24 July 2018 в 17:49

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

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

К сожалению, вызвать вызовы системы непосредственно в программе на C не так просто. Обычно glibc предоставляет оболочку, облегчающую работу, но glibc еще не добавил обертку для statx(2). К счастью, @whotwagner написал системный вызов stat(2), который показывает, как использовать системный вызов 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

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

больше файловых систем должно быть (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 для них не включали время создания.

Если, вернее, когда glibc добавляет поддержку системного вызова statx(2), stat будет скоро, и мы сможем использовать для этого старую команду stat. Но я не думаю, что это будет включено в выпуски LTS, даже если они получат новые ядра. Поэтому я не ожидаю, что stat в любой текущей версии (14.04, 16.04, 17.04, 17.10) будет когда-либо печатать время создания без ручного вмешательства.

6
ответ дан 18 July 2018 в 03:23

@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
50
ответ дан 18 July 2018 в 03:23

TL; DR: Просто запустите: sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs>

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

TL; DR:

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

Найдите имя названия раздела для вашего файла. df -T /path/to/your/file Результат будет выглядеть так (имя раздела будет первым): Filesystem Type 1K-blocks Used Available Use% Mounted on /dev/<your fs> ext4 7251432 3481272 3509836 50% / Найдите время создания для этого файла. sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs> На выходе найдите ctime.
3
ответ дан 18 July 2018 в 03:23

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

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

К сожалению, вызвать вызовы системы непосредственно в программе на C не так просто. Обычно glibc предоставляет оболочку, облегчающую работу, но glibc еще не добавил обертку для statx(2). К счастью, @whotwagner написал системный вызов stat(2), который показывает, как использовать системный вызов 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

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

больше файловых систем должно быть (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 для них не включали время создания.

Если, вернее, когда glibc добавляет поддержку системного вызова statx(2), stat будет скоро, и мы сможем использовать для этого старую команду stat. Но я не думаю, что это будет включено в выпуски LTS, даже если они получат новые ядра. Поэтому я не ожидаю, что stat в любой текущей версии (14.04, 16.04, 17.04, 17.10) будет когда-либо печатать время создания без ручного вмешательства.

6
ответ дан 24 July 2018 в 17:49
  • 1
    Спасибо за ссылку на github. Я несколько месяцев назад искал, когда вышел 4.11 и ничего не нашел, а потом забыл об этом. – WinEunuuchs2Unix 28 November 2017 в 04:34

@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
51
ответ дан 24 July 2018 в 17:49
  • 1
    Обратите внимание, что дата создания не является датой создания исходного файла, если файл является копией (например, - с датой изменения). Как только файл скопирован, дата изменения указана с оригинала, но дата создания - из копии. (theres - некоторое недоразумение в этом вопросе: askubuntu.com/questions/529885/… ) – Jacob Vlijm 29 September 2014 в 15:57
  • 2
    @JacobVlijm хорошо, да, конечно. Разве это не очевидно? Как же может быть иначе? Копия - это новый файл, который просто имеет то же содержимое, что и другое. Время модификации также изменяется для копии. Он устанавливается на момент, когда копия была создана, если вы явно не хотите, чтобы это не произошло с помощью cp -p или аналогичного. – terdon♦ 29 September 2014 в 17:42
  • 3
    Абсолютно, но в то же время, это было бы не так уж и нелогично, если бы, как мода. дата, где-то в файле дата будет сохранена, когда она возникла. Должен признаться, я не знал, что это не так, пока я не ответил на связанный вопрос. – Jacob Vlijm 29 September 2014 в 17:45
  • 4
    Просто попробовал, кстати, я просто скопировал файлы в наутилусе, дата модификации остается, как есть (была), м. дата предшествует дате создания. – Jacob Vlijm 29 September 2014 в 18:42
  • 5
    @demongolem да, версия CentOS df, похоже, не поддерживает параметр --output. В этом случае вы можете заменить эту строку на fs=$(df foo | awk '{a=$1}END{print a}', и функция также будет работать. Все, что я показываю в этом ответе, - это способ обернуть команду из принятого ответа способом, который может быть запущен напрямую для целей файла / каталога. – terdon♦ 24 February 2016 в 22:52

TL; DR: Просто запустите: sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs>

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

TL; DR:

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

Найдите имя названия раздела для вашего файла. df -T /path/to/your/file Результат будет выглядеть так (имя раздела будет первым): Filesystem Type 1K-blocks Used Available Use% Mounted on /dev/<your fs> ext4 7251432 3481272 3509836 50% / Найдите время создания для этого файла. sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs> На выходе найдите ctime.
3
ответ дан 24 July 2018 в 17:49

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

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