Muszę znaleźć czas utworzenia pliku, kiedy czytam kilka artykułów na ten temat, wszystkie wspominają, że nie ma rozwiązania (jak Site1 , Site2 ).
Kiedy próbowałem stat
polecenia, stwierdza Birth: -
.
Jak mogę znaleźć czas utworzenia pliku?
Muszę znaleźć czas utworzenia pliku, kiedy czytam kilka artykułów na ten temat, wszystkie wspominają, że nie ma rozwiązania (jak Site1 , Site2 ).
Kiedy próbowałem stat
polecenia, stwierdza Birth: -
.
Jak mogę znaleźć czas utworzenia pliku?
Odpowiedzi:
Istnieje sposób, aby poznać datę utworzenia katalogu, wykonaj następujące kroki:
Poznaj i- węzeł katalogu za pomocą ls -i
polecenia (powiedzmy na przykład, że jego X )
Dowiedz się, na której partycji Twój katalog jest zapisany za pomocą df -T /path
polecenia (powiedzmy, że jest włączony /dev/sda1
)
Teraz użyj tego polecenia: sudo debugfs -R 'stat <X>' /dev/sda1
W wyniku zobaczysz:
crtime: 0x4e81cacc:966104fc -- mon Sep 27 14:38:28 2013
crtime to data utworzenia pliku.
Co testowałem :
Zmodyfikowano go, tworząc plik.
Wypróbowałem polecenie i podało dokładny czas.
statx()
od marca 2019 r.
@Nux znalazł świetne rozwiązanie tego problemu, o którym wszyscy powinniście głosować. Postanowiłem napisać małą funkcję, której można użyć do bezpośredniego uruchamiania wszystkiego. Po prostu dodaj to do swojego
~/.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
}
Teraz możesz uruchomić, get_crtime
aby wydrukować daty utworzenia tylu plików lub katalogów, ile chcesz:
$ get_crtime foo foo/file
foo Wed May 21 17:11:08 2014
foo/file Wed May 21 17:11:27 2014
cp -p
lub podobnie.
df
nie obsługuje tej --output
opcji. W takim przypadku możesz zastąpić tę linię fs=$(df foo | awk '{a=$1}END{print a}'
i funkcja również będzie działać. W tej odpowiedzi pokazuję tylko sposób na zawinięcie polecenia z zaakceptowanej odpowiedzi w sposób, który można uruchomić bezpośrednio dla obiektów docelowych plików / katalogów.
Niemożność stat
pokazania czasu utworzenia wynika z ograniczenia stat(2)
wywołania systemowego , którego struktura powrotu nie zawierała pola dla czasu utworzenia. Począwszy od Linuksa 4.11 (tj. 17.10 i nowszych *) dostępne jest jednak nowe statx(2)
wywołanie systemowe , które zawiera czas utworzenia w strukturze zwracanej.
* I prawdopodobnie w starszych wersjach LTS przy użyciu jądra stosu włączania sprzętu (HWE). Sprawdź, uname -r
czy używasz jądra przynajmniej w wersji 4.11 w celu potwierdzenia.
Niestety wywołanie systemowe nie jest łatwe bezpośrednio w programie C. Zazwyczaj glibc zapewnia opakowanie, które ułatwia zadanie, ale glibc dodał tylko opakowanie statx(2)
w sierpniu 2018 r. (Wersja 2.28 , dostępna w 18.10). Na szczęście @whotwagner napisał przykładowy program C, który pokazuje, jak używać statx(2)
wywołania systemowego w systemach x86 i x86-64. Jego format wyjściowy jest taki sam, jak stat
domyślny, bez żadnych opcji formatowania, ale łatwo go zmodyfikować, aby wydrukować tylko datę urodzenia.
Najpierw sklonuj:
git clone https://github.com/whotwagner/statx-fun
Możesz skompilować statx.c
kod lub, jeśli chcesz tylko czas urodzenia, utworzyć birth.c
w sklonowanym katalogu następujący kod (który jest minimalną wersją statx.c
drukowania tylko znacznika czasu utworzenia, w tym precyzji nanosekundowej):
#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;
}
Następnie:
$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I {} date -d @{}
Mon Nov 27 14:34:51 UTC 2017
Teoretycznie powinno to uczynić czas tworzenia bardziej dostępnym:
debugfs
jest to narzędzie do systemów plików ext2 / 3/4 i nie nadaje się do użytku na innych)make
i linux-libc-dev
).Testowanie systemu XFS, na przykład:
$ 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: -
Nie działało to jednak w przypadku systemu plików NTFS i exfat. Wydaje mi się, że systemy plików FUSE dla tych nie zawierały czasu utworzenia.
Jeśli, a raczej kiedy glibc doda obsługę statx(2)
wywołania systemowego, stat
nastąpi wkrótce i będziemy mogli użyć do tego zwykłego starego stat
polecenia. Ale nie sądzę, że zostanie to przeniesione do wersji LTS, nawet jeśli otrzymają nowsze jądra. Nie spodziewam stat
się więc, że w żadnej bieżącej wersji LTS (14.04, 16.04 lub 18.04) kiedykolwiek wydrukuję czas tworzenia bez ręcznej interwencji.
Jednak w dniu 18.10 można bezpośrednio użyć statx
funkcji opisanej w man 2 statx
(zauważ, że strona podręcznika 18.10 nie zgadza się z twierdzeniem, że glibc nie dodał jeszcze opakowania).
1
?
TL; DR:
Po prostu uruchom:
sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs>
(Aby dowiedzieć się, jaki jest twój fs, uruchom df -T /path/to/your/file
, najprawdopodobniej tak będzie /dev/sda1
).
Długa wersja:
Uruchomimy dwa polecenia:
Znajdź nazwę partycji dla swojego pliku.
df -T /path/to/your/file
Dane wyjściowe będą wyglądać następująco (nazwa partycji jest pierwsza):
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/<your fs> ext4 7251432 3481272 3509836 50% /
Dowiedz się czas utworzenia tego pliku.
sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs>
W wyniku wyszukaj ctime
.