15%

Save 15% on All Hosting Services

Test your skills and get Discount on any hosting plan

Use code:

Skills
Get Started
12.12.2023

How to Find File Creation Date in Linux: Complete Technical Guide

Linux does not natively expose file birth time through most standard user-space tools, but the underlying data often exists — the challenge is knowing exactly where to look and which filesystem and kernel version you are running. On ext4, btrfs, xfs, and tmpfs filesystems with Linux kernel 4.11+, true birth timestamps (crtime) are stored in the inode and are retrievable through specific low-level utilities. On older filesystems or kernels, you must use a combination of inode metadata, system logs, and filesystem-specific debuggers to approximate creation time.

This guide covers every reliable method available in 2024, including their technical prerequisites, exact command syntax, known failure modes, and when each approach is appropriate for production system administration.

Why Linux File Creation Time Is Not Straightforward

Every file in Linux is described by an inode — a data structure storing metadata such as permissions, ownership, size, and timestamps. The POSIX standard historically defined three timestamps:

  • atime — last access time
  • mtime — last modification time (content changed)
  • ctime — inode change time (metadata or content changed)

Critically, ctime is not creation time. This is one of the most common misconceptions among administrators migrating from Windows environments. ctime updates whenever permissions change, ownership changes, or the file is renamed — it has nothing to do with when the file was first created.

True creation time, known as birth time or crtime, was added to the ext4 inode structure and is exposed via the statx() system call introduced in Linux kernel 4.11. However, many distributions shipped tools that did not surface this data until relatively recently, which is why the confusion persists.

Filesystem and Kernel Prerequisites

Before attempting any method, verify your environment:

# Check kernel version
uname -r

# Check filesystem type for a specific path
df -T /path/to/your/file

# Check filesystem mount options
findmnt -o TARGET,FSTYPE,OPTIONS /path/to/your/file
FilesystemBirth Time StoredRetrieval MethodNotes
ext4Yesstat, debugfsRequires kernel 4.11+ for stat
btrfsYesstatFull support, no extra tools needed
xfsYes (kernel 5.10+)statRequires xfs_db on older kernels
tmpfsNoN/AIn-memory, no persistent inode
ext2 / ext3NoN/ANo birth time field in inode
NFSDepends on serverstatInherited from server filesystem
FAT32 / exFATYesstatStored natively in directory entry

If you are running a VPS Hosting environment, the underlying filesystem is almost always ext4 or btrfs, meaning birth time data is available — you just need the right tools to surface it.

The stat command is the correct first tool to try. On modern systems with kernel 4.11+ and a supporting filesystem, it will directly display the Birth field.

stat /path/to/your/file

Example output on a modern ext4 system:

  File: /home/deploy/app/config.yml
  Size: 4096            Blocks: 8          IO Block: 4096   regular file
Device: fd01h/64769d    Inode: 2883591     Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/  deploy)   Gid: ( 1000/  deploy)
Access: 2024-03-15 09:22:14.812345678 +0000
Modify: 2024-03-10 14:05:33.123456789 +0000
Change: 2024-03-10 14:05:33.123456789 +0000
 Birth: 2024-03-08 11:47:02.987654321 +0000

If the Birth field shows - (a dash) instead of a timestamp, one of the following is true:

  • The filesystem does not store birth time (ext2/ext3)
  • The kernel is older than 4.11
  • The stat binary is outdated and does not call statx()
  • The file was created before the filesystem was upgraded from ext3 to ext4

Extracting only the birth timestamp programmatically:

stat --format="%w" /path/to/your/file
# Returns '-' if unavailable, or ISO 8601 timestamp if available

stat --format="%W" /path/to/your/file
# Returns Unix epoch integer (0 if unavailable)

The %W format returning 0 is a reliable programmatic check for whether birth time is genuinely unavailable.

Method 2: Using debugfs for ext4 Filesystems

debugfs is the definitive low-level tool for ext4 inode inspection. It reads the raw inode structure and can expose crtime even when stat fails due to an older userspace binary.

Step 1: Identify the inode number of your file

ls -i /path/to/your/file
# Output example: 2883591 /path/to/your/file

Step 2: Identify the block device hosting the filesystem

df /path/to/your/file
# Output shows the device, e.g., /dev/sda1 or /dev/vda1

Step 3: Query debugfs with the inode number

sudo debugfs -R 'stat <2883591>' /dev/vda1

Replace 2883591 with your actual inode number and /dev/vda1 with your actual device. The output will include a crtime field:

Inode: 2883591   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 3421897654    Version: 0x00000000:00000001
User:  1000   Group:  1000   Project:     0   Size: 4096
File ACL: 0
Links: 1   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x65ee1f4d:1d4c5800 -- Sun Mar 10 14:05:33 2024
 atime: 0x65f4a1ae:c6b5c000 -- Fri Mar 15 09:22:14 2024
 mtime: 0x65ee1f4d:1d4c5800 -- Sun Mar 10 14:05:33 2024
crtime: 0x65e4b2c6:eb851400 -- Thu Mar 08 11:47:02 2024
Size of extra inode fields: 28

Important operational note: debugfs opens the filesystem in read-only mode by default when using -R, but you should still avoid running it on a heavily active filesystem without first unmounting or using a snapshot. On production Dedicated Servers, always prefer running debugfs against a filesystem snapshot or a quiesced volume to avoid reading inconsistent inode state.

Alternative syntax using filename directly:

sudo debugfs -R "stat /path/to/your/file" /dev/vda1

Note that the path here must be relative to the filesystem root, not the system root. If /dev/vda1 is mounted at /, then /path/to/your/file works as-is.

Method 3: Using xfs_db for XFS Filesystems

On XFS filesystems (common on RHEL/CentOS/Rocky Linux systems), the equivalent of debugfs is xfs_db.

# Get inode number first
ls -i /path/to/your/file

# Unmount or use read-only mode
sudo xfs_db -r /dev/sda1 -c "inode <inode_number>" -c "print"

Look for the v3.crtime field in the output. XFS v5 (the default since RHEL 7) stores birth time natively. XFS v4 does not.

Method 4: Using btrfs Subvolume and File Inspection

On btrfs, stat with a modern kernel is sufficient and fully reliable. However, for deeper inspection:

sudo btrfs inspect-internal dump-tree /dev/sdb | grep -A 20 "inode ref"

For practical purposes on btrfs, the stat output Birth field is authoritative.

Method 5: Querying statx() Directly via Python

When shell tools give inconsistent results, calling the statx() syscall directly from Python provides a definitive answer:

import os
import stat

result = os.stat("/path/to/your/file")
# st_birthtime is available on systems where statx() returns it
if hasattr(result, 'st_birthtime'):
    import datetime
    birth = datetime.datetime.fromtimestamp(result.st_birthtime)
    print(f"Birth time: {birth}")
else:
    print("Birth time not available on this platform/filesystem")

For more precise nanosecond resolution, use the ctypes module to call statx() directly — this is useful in forensic scripts where timestamp precision matters.

Method 6: Searching System Logs

When filesystem-level birth time is unavailable — for example, on ext3 filesystems or files that predate a filesystem conversion — system logs become the fallback.

Search systemd journal:

journalctl --since="2024-01-01" | grep "your_filename"

Search traditional syslog:

grep "your_filename" /var/log/syslog
grep "your_filename" /var/log/messages

Search audit log (if auditd is configured):

sudo ausearch -f /path/to/your/file

The audit subsystem is the most reliable log-based method because it records openat(), creat(), and rename() syscalls with precise timestamps. However, it must be configured in advance — you cannot retroactively audit file creation events that occurred before auditd was enabled.

Enable file creation auditing for a directory:

sudo auditctl -w /var/www/html -p w -k web_file_creation

This watches /var/www/html for write events, tagging them with the key web_file_creation for easy retrieval.

Method 7: Using ls — Understanding Its Limitations

The ls command is frequently cited in guides as a way to check creation time, but this requires significant qualification.

ls -l --time=birth /path/to/your/file
ls -l --time=creation /path/to/your/file  # synonym on some systems

Critical caveat: ls --time=birth only works on GNU coreutils 8.25+ and only when the underlying filesystem and kernel support birth time. If birth time is unavailable, ls silently falls back to mtime without any warning. This silent fallback is a significant operational hazard — you may believe you are reading creation time while actually reading modification time.

Always verify with stat first. Use ls for display purposes only, not for scripted logic.

# Safer: check stat output explicitly before relying on ls
BIRTH=$(stat --format="%W" /path/to/your/file)
if [ "$BIRTH" -eq 0 ]; then
    echo "Birth time unavailable, falling back to mtime"
    stat --format="%y" /path/to/your/file
else
    echo "Birth time: $(date -d @$BIRTH)"
fi

Method Comparison and Decision Matrix

MethodAccuracyFilesystem RequirementRoot RequiredWorks Without Prior Setup
stat (Birth field)Exactext4, btrfs, xfs v5NoYes
debugfsExactext4 onlyYesYes
xfs_dbExactXFS v5 onlyYesYes
statx() via PythonExactSame as statNoYes
journalctl / syslogApproximateAnyNoDepends on log retention
auditdExactAnyYes (setup)No (requires prior config)
ls --time=birthExact or silent fallbackext4, btrfs, xfs v5NoYes (unreliable fallback)

Real-World Edge Cases and Pitfalls

File copied vs. moved: When a file is copied (cp), the destination gets a new inode with a new birth time. When a file is moved within the same filesystem (mv), the inode is preserved and birth time is unchanged. Cross-filesystem mv behaves like cp + rm, creating a new inode.

Filesystem conversion from ext3 to ext4: Files that existed before the conversion will have a crtime of zero in their inode, because ext3 never populated that field. debugfs will show crtime: 0x00000000:00000000. In this case, mtime at the time of conversion is the best approximation.

Docker and container environments: Container filesystems (overlay2, aufs) may not propagate birth time correctly. Files inside containers may show birth time as the container start time rather than actual file creation time.

NFS mounts: Birth time availability depends entirely on the NFS server's filesystem. The client has no independent birth time data.

Backup restoration: Files restored from tar archives typically get a new inode and thus a new birth time reflecting the restoration date, not the original creation date. Use tar --preserve-permissions and check mtime for the closest approximation to original creation time.

For administrators managing web applications on VPS with cPanel, file timestamp integrity is particularly important during migrations — always verify inode metadata after restoring from backup.

Enabling Birth Time Support: Filesystem Tuning

If you are setting up a new server and want guaranteed birth time support, ensure the following:

For ext4 — verify inode size is 256 bytes (required for crtime field):

sudo tune2fs -l /dev/vda1 | grep "Inode size"
# Should return: Inode size: 256

If inode size is 128, birth time cannot be stored. This requires reformatting — it cannot be changed on an existing filesystem.

Create new ext4 filesystem with 256-byte inodes (default since e2fsprogs 1.41):

sudo mkfs.ext4 -I 256 /dev/vdb1

Verify kernel supports statx():

uname -r  # Must be >= 4.11

When provisioning new infrastructure — whether Shared Web Hosting or bare-metal Dedicated Servers — confirm the filesystem inode size before deploying applications that depend on birth time metadata.

Practical Checklist for Determining File Creation Time

Use this decision tree when you need to find a file's creation date:

  • Check kernel version first: uname -r — must be 4.11+ for stat to show Birth
  • Check filesystem type: df -T /path/to/file — ext4, btrfs, or xfs v5 required
  • Run stat on the file: If Birth field shows a timestamp, you have your answer
  • If Birth shows -: Run debugfs (ext4) or xfs_db (xfs) with the inode number
  • If filesystem is ext3 or ext2: Fall back to mtime as best approximation
  • If you need audit-grade accuracy going forward: Configure auditd now
  • If the file was recently created: Check journalctl for corroborating log entries
  • In scripts: Always check stat --format="%W" for 0 before trusting the value
  • After migrations or restores: Treat birth time as suspect; cross-reference with mtime and backup manifests

For environments where file integrity and timestamp accuracy are security requirements — such as applications handling SSL Certificates and cryptographic key files — combining auditd with filesystem-level birth time gives you a two-layer verification approach that is defensible in security audits.

FAQ

Does Linux always store file creation time?

No. Only filesystems with 256-byte inodes (ext4, btrfs, xfs v5) store birth time. ext2 and ext3 do not have a birth time field in their inode structure. Even on supporting filesystems, files created before a filesystem upgrade from ext3 to ext4 will have a zero birth time.

What is the difference between ctime and birth time in Linux?

ctime is the inode change time — it updates whenever file metadata (permissions, ownership, link count) or content changes. It is not creation time. Birth time (crtime) is set once when the file is first created and never changes. Many administrators confuse these two, which leads to incorrect audit conclusions.

Can I recover file creation time after it has been lost?

If the inode's crtime field is zero or the filesystem does not support it, the original creation time cannot be recovered from the filesystem alone. Your best options are: check auditd logs if they were configured, search application logs, or consult backup manifests that recorded file metadata at backup time.

Why does ls --time=creation show the wrong time?

ls silently falls back to mtime when birth time is unavailable, without displaying any warning. This is a known behavioral issue in GNU coreutils. Always use stat --format="%W" to programmatically verify whether birth time is genuinely available before relying on ls output.

Which command gives the most reliable file creation time on ext4?

debugfs -R 'stat <inode_number>' /dev/device is the most reliable method on ext4 because it reads the raw inode structure directly, bypassing any userspace tool limitations. For day-to-day use on kernel 4.11+, stat filename with the Birth field is equivalent and far more convenient.

15%

Save 15% on All Hosting Services

Test your skills and get Discount on any hosting plan

Use code:

Skills
Get Started