Я должен найти время создания файла, когда я прочитал некоторые статьи об этой проблеме, все упомянули, что нет никакого решения (как Site1, Site2).
Когда я попробовал stat
команда, указывает это Birth: -
.
Таким образом, как я могу найти время создания файла?
Есть способ узнать дату создания каталога, просто выполните следующие действия:
Узнайте inode каталога с помощью ls -i
команда (скажем, ее X )
Узнайте, на каком разделе сохранен ваш каталог, с помощью команды df -T / path
(скажем, это на / dev / sda1
)
Теперь используйте эту команду: sudo debugfs -R 'stat
В выводе вы увидите:
crtime: 0x4e81cacc:966104fc -- mon Sep 27 14:38:28 2013
crtime - дата создания вашего файла.
Что я тестировал :
Изменил его, создав файл.
Я попробовал команда, и она дала точное время.
@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
TL; DR:
Просто беги:
sudo debugfs -R 'stat / path / to / your / file' / dev /
(Чтобы определить вашу fs, запустите df -T / path / to / your / file
, скорее всего, это будет / dev / sda1
).
Длинная версия:
Мы собираемся запустить две команды:
Узнать имя раздела для ваш файл.
df -T / путь / к / вашему / файлу
Вывод будет выглядеть следующим образом (сначала имя раздела):
Тип файловой системы Используется 1K-блоков Доступно Использовано% Установлено на
/ dev / <ваша фс> ext4 7251432 3481272 3509836 50% /
Узнать время создания этого файла.
sudo debugfs -R 'stat / path / to / your / file' / dev /
В выходных данных найдите ctime
.
Неспособность 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
Теоретически это должно сделать время создания более доступным:
debugfs
- это инструмент для файловых систем ext2 / 3/4, который нельзя использовать в других) 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 для них не учитывали время создания.
Моя ОС (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
:
Вывод stat
в файловой системе ext4 и файловой системе btrfs:
(Скопировано из моего другого ответа на UNIX и Linux Stack Exchange )