@Nux found a great solution for this which you should all upvote. I decided to write a little function that can be used to run everything directly. Just add this to your
~/.bashrc.
The inability of stat to show the creation time is due to limitation of the stat(2) system call, whose return struct doesn't include a field for the creation time. Starting with Linux 4.11 (i.e., 17.10 and newer*), however, the new statx(2) system call is available, which does include a creation time in its return struct.
* And possibly on older LTS releases using the hardware enablement stack (HWE) kernels. Check uname -r to see if you are using a kernel at least at 4.11 to confirm.
Unfortunately, it's not easy to call system calls directly in a C program. Typically glibc provides a wrapper that makes the job easy, but glibc only added a wrapper for statx(2) in August 2018 (version 2.28, available in 18.10). The stat command itself gained support for statx(2) only in GNU coreutils 8.31 (released in March 2019), however, even Ubuntu 20.04 only has coreutils 8.30.
But I don't think this will be backported to LTS releases even if they do get, or are already on, newer kernels or glibcs. So, I don't expect stat on any current LTS release (16.04, 18.04 or 20.04) to ever print the creation time without manual intervention.
On 18.10 and newer, you can directly use the statx function as described in man 2 statx (note that the 18.10 manpage is incorrect in stating that glibc hasn't added the wrapper yet).
And in Ubuntu 20.10, you will be able to use stat directly:
# 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
For older systems, luckily, @whotwagner wrote a sample C program that shows how to use the statx(2) system call on x86 and x86-64 systems. Its output is the same format as stat's default, without any formatting options, but it's simple to modify it to print just the birth time.
First, clone it:
git clone https://github.com/whotwagner/statx-fun
You can compile the statx.c code, or, if you just want the birth time, create a birth.c in the cloned directory with the following code (which is a minimal version of statx.c printing just the creation timestamp including nanosecond precision):
#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;
}
Then:
$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I {} date -d @{}
Mon Nov 27 14:34:51 UTC 2017
In theory this should make the creation time more accessible:
more filesystems should be supported than just the ext* ones (debugfs is a tool for ext2/3/4 filesystems, and unusable on others)
you don't need root to use this (except for installing some required packages, like make and linux-libc-dev).
My OS (Ubuntu 20.04, which comes with Linux kernel 5.4.0-28 and GLIBC 2.31) only came with GNU coreutils 8.30, so I had to get it to work by compiling version 8.32 of GNU coreutils from source. It was a relatively pain-free procedure.
Afterwards, both ls and stat could work with birth time.
Output of ls -l --time=birth --time-style=full-iso --no-group:
Output of stat on an ext4 file system and a btrfs file system:
You may need the file creation time in human readable but not standard format to use in bash shell script pipeline. For example, to prefixing the file name for appropriate sorting in the file manager. I modified @terdon solution for this purpose as following.
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 $(date -d "${crtime}" | sed 's/://g'| sed 's/-//g')
done
}
There is a way to know the creation date of a directory , just follow these steps :
Know the inode of the directory by
ls -i
command (lets say for example its X)Know on which partition your directory is saved by
df -T /path
command ( lets say its on/dev/sda1
)Now use this command :
sudo debugfs -R 'stat <X>' /dev/sda1
You will see in the output :
crtime is the creation date of your file .
What I tested :
Modified it by creating a file .
I tried the command and it gave an exact time .
@Nux found a great solution for this which you should all upvote. I decided to write a little function that can be used to run everything directly. Just add this to your
~/.bashrc
.Now, you can run
get_crtime
to print the creation dates of as many files or directories as you like:The inability of
stat
to show the creation time is due to limitation of thestat(2)
system call, whose return struct doesn't include a field for the creation time. Starting with Linux 4.11 (i.e., 17.10 and newer*), however, the newstatx(2)
system call is available, which does include a creation time in its return struct.* And possibly on older LTS releases using the hardware enablement stack (HWE) kernels. Check
uname -r
to see if you are using a kernel at least at 4.11 to confirm.Unfortunately, it's not easy to call system calls directly in a C program. Typically glibc provides a wrapper that makes the job easy, but glibc only added a wrapper for
statx(2)
in August 2018 (version 2.28, available in 18.10). Thestat
command itself gained support forstatx(2)
only in GNU coreutils 8.31 (released in March 2019), however, even Ubuntu 20.04 only has coreutils 8.30.But I don't think this will be backported to LTS releases even if they do get, or are already on, newer kernels or glibcs. So, I don't expect
stat
on any current LTS release (16.04, 18.04 or 20.04) to ever print the creation time without manual intervention.On 18.10 and newer, you can directly use the
statx
function as described inman 2 statx
(note that the 18.10 manpage is incorrect in stating that glibc hasn't added the wrapper yet).And in Ubuntu 20.10, you will be able to use
stat
directly:For older systems, luckily, @whotwagner wrote a sample C program that shows how to use the
statx(2)
system call on x86 and x86-64 systems. Its output is the same format asstat
's default, without any formatting options, but it's simple to modify it to print just the birth time.First, clone it:
You can compile the
statx.c
code, or, if you just want the birth time, create abirth.c
in the cloned directory with the following code (which is a minimal version ofstatx.c
printing just the creation timestamp including nanosecond precision):Then:
In theory this should make the creation time more accessible:
debugfs
is a tool for ext2/3/4 filesystems, and unusable on others)make
andlinux-libc-dev
).Testing out an xfs system, for example:
However, this didn't work for NTFS and exfat. I guess the FUSE filesystems for those didn't include the creation time.
TL;DR: Just run:
sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs>
(To figure out your fs, run
df -T /path/to/your/file
, most likely it's going to be/dev/sda1
).Long version:
We are going to run two commands:
Find out the name of partition name for your file.
The output is going to look like this (partition name is first):
Find out creation time for that file.
In the output, look for
ctime
.My OS (Ubuntu 20.04, which comes with Linux kernel 5.4.0-28 and GLIBC 2.31) only came with GNU coreutils 8.30, so I had to get it to work by compiling version 8.32 of GNU coreutils from source. It was a relatively pain-free procedure.
Afterwards, both
ls
andstat
could work with birth time.Output of
ls -l --time=birth --time-style=full-iso --no-group
:Output of
stat
on an ext4 file system and a btrfs file system:(Copied from my other answer on UNIX & Linux Stack Exchange)
You may need the file creation time in human readable but not standard format to use in bash shell script pipeline. For example, to prefixing the file name for appropriate sorting in the file manager. I modified @terdon solution for this purpose as following.
date -d ...
parses date time string;sed
removes special characters:
and-
;Which produses: