stat Command Explained

stat Command Explained

stat shows you everything about a file’s metadata that ls -l only hints at. Where ls -l gives a fast, compact summary, stat gives you the full picture, including a few fields that do not show up anywhere else.

Basic usage

stat report.pdf
#   File: report.pdf
#   Size: 245678        Blocks: 480        IO Block: 4096   regular file
# Device: 8,1    Inode: 1310990     Links: 1
# Access: (0644/-rw-r--r--)  Uid: ( 1000/  colton)   Gid: ( 1000/  colton)
# Access: 2026-07-09 09:00:12.000000000 -0500
# Modify: 2026-07-08 22:14:05.000000000 -0500
# Change: 2026-07-08 22:14:05.000000000 -0500
#  Birth: 2026-07-01 10:00:00.000000000 -0500

This single command reports far more than ls -l report.pdf would: the exact byte size, the number of disk blocks it occupies, the inode number, the number of hard links, permissions in both numeric and symbolic form, owner and group with both the numeric ID and the resolved name, and up to four separate timestamps.

The inode number and what it actually means

stat -c %i file.txt
# 1310990

An inode is the real data structure on disk holding a file’s metadata and pointers to its actual content blocks. A filename is essentially just a label in a directory pointing at an inode; it is not the file itself. This matters directly when working with hard links:

ln original.txt hardlink.txt
stat -c %i original.txt hardlink.txt
# 1310990
# 1310990

Two different filenames sharing the same inode number are, for all practical purposes, the exact same file with two names. Editing one edits the other, because there is genuinely only one underlying file. stat is the standard way to confirm this, since ls alone does not surface inode numbers by default.

The three (or four) timestamps

stat file.txt
# Access: 2026-07-09 09:00:12   <- atime: last read/opened
# Modify: 2026-07-08 22:14:05   <- mtime: last content change
# Change: 2026-07-08 22:14:05   <- ctime: last metadata change
#  Birth: 2026-07-01 10:00:00    <- creation time, if the filesystem supports it

These are frequently confused, particularly modify time and change time:

  • atime (access time) updates whenever the file is read, even if nothing changes.
  • mtime (modify time) updates only when the file’s actual content changes.
  • ctime (change time) updates when the file’s metadata changes: permissions, ownership, or link count, independent of whether the content itself changed.
  • Birth time (not available on every filesystem) records true creation time, and unlike the other three, it never updates after the file is created.
chmod 600 file.txt
stat file.txt
# Modify: unchanged  (content was not touched)
# Change: just updated  (permissions changed, so ctime updates)

This distinction between mtime and ctime resolves a common point of confusion: running chmod or chown on a file updates its change time but leaves its modification time exactly as it was, since the actual content was never touched.

Extracting a single field with —format

stat -c %s file.txt
# 245678                (size in bytes, nothing else)

stat -c %U file.txt
# colton                (owner username)

stat -c %a file.txt
# 644                    (numeric permission mode)

stat -c %Y file.txt
# 1783623245              (modification time as a Unix timestamp)

For scripting, requesting a single field with -c (or --format) and a format specifier is far more useful than parsing the full human-readable output, since it returns exactly one clean value that can be captured directly into a variable.

# A common scripting pattern
size=$(stat -c %s largefile.iso)
echo "File is $size bytes"

if [ "$(stat -c %U file.txt)" != "colton" ]; then
  echo "Warning: unexpected file owner"
fi

stat on directories

stat /var/log
#   File: /var/log
#   Size: 4096          Blocks: 8          IO Block: 4096   directory

Running stat on a directory reports its own metadata, permissions, owner, inode, timestamps, exactly as it would for a regular file. The reported size reflects the size of the directory entry structure itself (how much space is used to store the list of filenames inside it), not the combined size of everything contained within it. This is a common point of confusion: checking stat /var/log and expecting to see the total size of every log file inside will not match, since that total is what du -sh /var/log reports instead, a fundamentally different measurement.

Frequently Asked Questions

What does the stat command do?

stat displays detailed metadata about a file or directory: its size, permissions in both symbolic and numeric form, owner and group, inode number, number of hard links, and three separate timestamps. It goes considerably deeper than ls -l, which shows only a subset of this information in a compact single-line format.

What is an inode and why does stat show its number?

An inode is the actual data structure on disk that stores a file’s metadata and points to where its content blocks are located. A filename is really just a label pointing at an inode; multiple filenames (hard links) can point at the exact same inode. stat shows the inode number so you can confirm whether two different filenames actually refer to the same underlying file content or are genuinely separate files that merely look similar.

What are the three timestamps that stat shows for every file?

Access time (atime) records when the file was last read or opened. Modify time (mtime) records when the file’s actual content last changed. Change time (ctime) records when the file’s metadata, permissions, ownership, or link count last changed, which is not the same as when the content changed. A chmod, for instance, updates ctime without touching mtime at all, since the file’s content was not modified, only its permissions.

How is stat different from ls -l for checking file details?

ls -l shows a compact summary: permissions, link count, owner, group, size, and one timestamp (modification time), all on a single line. stat shows the same core information in a more spread-out, detailed format, plus additional fields ls -l does not show at all, including the inode number, all three timestamps instead of just one, the number of blocks the file occupies on disk, and the exact block size.

Can I use stat to get just one specific piece of information, like a file’s size in bytes?

Yes, use the —format (or -c) flag with a format specifier, such as stat -c %s file.txt to print only the size in bytes, or stat -c %U file.txt to print only the owner’s username. This is especially useful in scripts that need a single piece of file metadata as a plain value rather than the full human-readable stat report.

Does stat work on directories as well as regular files?

Yes, running stat on a directory shows the same kind of metadata: its own permissions, owner, group, inode number, and timestamps. A directory’s size as reported by stat reflects the size of the directory entry structure itself, not the total size of the files inside it, which is a common point of confusion since it does not match what du would report for that same directory.