Linux stat Command: Display Detailed File Metadata
stat is a command that shows detailed information about the size, permissions, owner, inode, number of hard links, allocated blocks, and various timestamps of a file or directory. It allows you to check more metadata than ls -l and is also useful for shell scripts because you can output only the desired fields in a consistent format.
In this article, we explain how to read the default output of GNU Coreutils' stat, the differences between atime/mtime/ctime/Birth, symbolic links, file system information, and how to use --format.
What is the stat command?
stat retrieves the status information managed by the file system, that is, metadata, rather than the contents of the file. You just need to specify the file or directory you want to check as an argument.
stat report.txt stat /etc stat /usr/bin/bash
It has a different purpose from the file command, which reads the file directly to analyze its contents. file guesses the format, whereas stat shows file system information such as size, permissions, ownership, timestamps, and inode.
Basic Syntax and Usage
stat [option] file...
You can specify not only a single file but also multiple paths at once.
stat file1.txt file2.txt stat src tests stat "annual report.pdf"
For filenames starting with a hyphen, specify them after -- so they are not misinterpreted as options.
stat -- -sample.txt
You can check the version of GNU stat and supported options with the following command.
stat --version stat --help info '(coreutils) stat invocation'
How to Read Basic Output
When you run stat on a regular file, you will see information similar to the following. Actual values and some fields may vary depending on the file system and operating system.
File: report.txt Size: 4096 Blocks: 8 IO Block: 4096 regular file Device: 8,1 Inode: 1234567 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 1000/ user) Gid: ( 1000/ user) Access: 2026-09-21 10:15:30.000000000 +0900 Modify: 2026-09-21 10:14:02.000000000 +0900 Change: 2026-09-21 10:14:02.000000000 +0900 Birth: 2026-09-20 19:42:11.000000000 +0900
Each item has the following meaning.
| Item | Meaning |
|---|---|
File |
The name of the file or directory being queried. |
Size |
The logical size of the file, usually displayed in bytes. |
Blocks |
The number of blocks allocated to the file. Sparse files or compressed file systems may show a large difference between the logical size and actual allocation. |
IO Block |
Recommended block size information for efficient input/output. |
Device |
The number identifying the device to which the file belongs. |
Inode |
This is the inode number that identifies the file metadata within the file system. |
Links |
The number of hard links pointing to the same inode. |
Access |
Shows permissions and file type in octal and symbolic form. |
Uid, Gid |
The numeric ID and name of the owner user and group. |
Access, Modify, Change, Birth |
Timestamps regarding access, content modification, status change, and creation. |
Difference between ls -l and stat
| Comparison items | ls -l |
stat |
|---|---|---|
| Main Purpose | Quickly compare multiple files in list form. | Check detailed metadata of the specified file. |
| Basic time | Mainly displays the modification time briefly. | Displays access, modification, status change, and creation times separately. |
| inode and blocks | You need to add options to see some information. | Shows inode, number of links, allocated blocks, etc., in the default output. |
| Script output | Parsing human-readable lists can be unstable depending on the environment. | You can directly specify the necessary fields with --format. |
| File system information | Not provided directly. | Use -f to display the file system status where the file is located. |
When browsing names, sizes, and permissions of multiple files, ls -l is convenient, and if you need accurate fields of a single file or values for automation, stat is suitable.
Understanding file size and allocated blocks
Checking logical size
The default output Size is the total number of bytes that the file represents. To output only the needed value, use %s.
stat -c '%s' disk.img stat -c '%n: %s bytes' file1 file2
The Size of a directory is not the sum of all the files within it. It is the size of the directory itself that stores the directory entries. To check the total usage of the contents, use du.
Calculating allocated space
%b outputs the number of allocated blocks, and %B outputs the size in bytes of a single block.
stat -c 'size=%s blocks=%b block-size=%B' disk.img
The approximate allocated byte count can be calculated with %b × %B. Sparse files may have actual allocated space that is much smaller than the logical size, and with features like file system compression or shared blocks, it is difficult to determine physical storage usage from this value alone.
Checking permissions and ownership
Outputting octal permissions and symbolic permissions
%a outputs octal permissions, and %A outputs human-readable permissions including the file type.
stat -c '%a %A %n' script.sh
The output can be in the following form.
755 -rwxr-xr-x script.sh
Displaying owner and group
%U and %G display the username and group name, while %u and %g display the numeric UID and GID.
stat -c 'owner=%U(%u) group=%G(%g)' report.txt
In environments where the name corresponding to a numeric ID cannot be found, the name field may be displayed differently.
Checking inode and hard links
Displaying inode number
%i displays the inode number that identifies the file within the file system.
stat -c '%i %n' report.txt
Inode numbers are not globally unique across file system boundaries. To compare whether files are the same, you must consider the device information along with the inode.
Checking the Number of Hard Links
%h is the number of hard links pointing to that inode.
stat -c 'inode=%i links=%h name=%n' original.txt copy-link.txt
If the device and inode of two paths are the same, they may be hard links pointing to the same file data. Symbolic links have separate inodes, so they are not judged in the same way.
Differences Between atime, mtime, ctime, and Birth
The timestamp names are similar, but the events they record are different. In particular, it is important not to mistake ctime for the creation time.
| Time | Meaning | Examples that Can Be Changed |
|---|---|---|
atime |
The last access time of the file data. | File read. However, depending on mount options and cache policies, it may not be updated each time. |
mtime |
The last time the file content was modified. | Writing file data or changing the content length. |
ctime |
The last time the inode status information was changed. | Changes in permissions, owner, number of links, name changes, etc. Not the creation time. |
Birth |
The time the file was created. | Recorded once at creation if supported and does not change with normal status changes. |
Print human-readable time
%x, %y, %z, and %w print atime, mtime, ctime, and Birth in a human-readable format, respectively.
stat -c 'atime=%x mtime=%y ctime=%z birth=%w' report.txt
On file systems that do not support Birth or cannot obtain its value, %w may be displayed as a hyphen.
Output in seconds since the Epoch
Uppercase %X, %Y, %Z, %W output the respective times in seconds since the Unix Epoch.
stat -c 'atime=%X mtime=%Y ctime=%Z birth=%W' report.txt
When Birth is unknown, %W outputs 0. While the Epoch value is convenient for sorting or numeric comparison, the differences in time precision provided by file systems and operating systems should be considered.
Checking symbolic link information
Viewing the metadata of the link itself
By default, GNU stat does not follow symbolic links and examines the link itself.
stat current.log stat -c '%N | inode=%i | type=%F' current.log
%N can display the file name in quotes along with its target for links.
View target metadata with -L
Using -L or --dereference checks the status of the actual target that the link points to.
stat -L current.log stat -L -c '%n | inode=%i | type=%F | size=%s' current.log
Broken symbolic links cannot check the target, so using -L will cause an error.
Print only the desired fields
Using -c and --format
-c or --format outputs the results in the specified format and adds a line break for each file.
stat -c '%n %s %a %U:%G' file1 file2 stat --format='name=%n type=%F inode=%i' report.txt
It is safe to enclose the format string in single quotes so that the shell does not interpret it.
Compose multiple lines with --printf
--printf interprets backslash escapes but does not add automatic line breaks. Insert \n directly where necessary.
stat --printf='name=%n\nsize=%s\nmode=%a\n' report.txt
When processing multiple files, the format string should also include separators between files.
Frequently used format specifiers
| Specifier | Output content |
|---|---|
%n |
The file name. |
%N |
The quoted file name, and if it is a symbolic link, it may also include information about the target. |
%F |
The file type, such as a regular file, directory, or symbolic link. |
%s |
This is the total size (in bytes). |
%b |
This is the number of allocated blocks. |
%B |
This is the byte size of a block represented by %b. |
%a |
Octal permissions. |
%A |
Symbolic permissions including file type. |
%u, %g |
The numeric UID and GID of the owner. |
%U, %G |
The owner's username and group name. |
%i |
The inode number. |
%h |
Number of hard links. |
%m |
The mount point the file belongs to. |
%x, %X |
Display the last access time in a human-readable format or as Epoch seconds. |
%y, %Y |
Display the last content modification time in a human-readable format or as Epoch seconds. |
%z, %Z |
Display the last status change time in a human-readable format or as Epoch seconds. |
%w, %W |
Display the creation time in a human-readable format or as Epoch seconds; if unknown, show a hyphen or 0. |
%C |
Display the SELinux security context in supported environments. |
Check file system information
View filesystem status with -f
Using -f or --file-system displays information about the file system where the path is located, rather than the file itself.
stat -f / stat --file-system /home
You can check the file system type, total blocks, available blocks, number of inodes, and maximum file name length.
Using file system format specifiers
In -f mode, the meaning is different from the specifiers for files. For example, %T indicates the human-readable file system type, %b represents total data blocks, and %a shows the number of blocks available to regular users.
stat -f -c 'type=%T total=%b available=%a block-size=%S' /
To compare human-readable disk usage, df -h might be more convenient, and to extract only file system fields required for automation, stat -f -c is useful.
Remote file systems and cache policies
In supported versions of GNU Coreutils, you can specify the cache usage method when retrieving remote file system attributes with --cached=MODE.
| Modes | Action |
|---|---|
default |
Whether to use cache is left to the file system's default policy. |
always |
Use cached attributes if possible. It may be fast, but may not be up-to-date. |
never |
Try to synchronize with the latest attributes if possible. Remote access latency may increase. |
stat --cached=never /mnt/remote/report.txt
The actual guarantee level depends on remote file systems like NFS and mounting settings. Check if the installed version supports this option with stat --help.
Shell script usage examples
Branching based on file size
path='archive.tar' size=$(stat -c '%s' -- "$path") || exit 1 if [ "$size" -gt 104857600 ]; then printf '%s\n' 'The file is larger than 100 MiB.' fi
In environments where files can change between checking and use, do not assume that metadata checked once will remain the same until subsequent operations.
Compare modification times numerically
left_mtime=$(stat -c '%Y' -- file-a) right_mtime=$(stat -c '%Y' -- file-b) if [ "$left_mtime" -gt "$right_mtime" ]; then printf '%s\n' 'file-a was modified more recently.' fi
Relying solely on a single timestamp for backup or deployment decisions can cause problems due to clock differences, restored timestamps, or simultaneous modifications. If necessary, also use checksums or version information.
Frequently used stat commands
| Command | Purpose |
|---|---|
stat file |
Displays all metadata of the file. |
stat -L link |
Displays information about the target that the symbolic link points to. |
stat -c '%s' file |
Outputs the file size in bytes. |
stat -c '%a %n' file |
Displays the octal permissions and file name. |
stat -c '%U:%G' file |
Displays the owner user and group. |
stat -c '%i %h %n' file |
Displays the inode, number of hard links, and file name. |
stat -c '%y' file |
Displays the last modification time of the content. |
stat -c '%Y' file |
Prints the last modification time as Epoch seconds. |
stat -f path |
Displays information about the file system containing the given path. |
stat -t file |
Outputs in a concise, single-line format with fixed fields. |
Precautions when using
ctime is not the creation time
ctime is the change time, that is, the time when the file's status information was modified. It is not an abbreviation for creation time, and the creation time can be provided in a separate Birth field.
Birth and atime are not always the expected values.
The creation time may not be supported depending on the file system, kernel, and mount method. atime may also not be updated immediately every time a file is read due to mount policies like noatime or relatime and caching.
Do not directly parse the output text.
The default output is in a human-readable format and may vary depending on the operating system, Coreutils version, and locale. For automation, select only the needed fields with -c, and consider that filenames may contain spaces or line breaks.
FAQ
How can I check only the octal permissions of a file?
Use stat -c '%a' filename. If you also need the filename, use stat -c '%a %n' filename.
What is the difference between mtime and ctime?
mtime is the time when the file content was last modified, and ctime is the time when the inode status, such as permissions, ownership, and link count, was last changed. ctime is not the file creation time.
Why is Birth shown as a hyphen?
It is because the file system or operating system in use does not provide the creation time, or stat could not obtain that value. In this case, %w outputs a hyphen, and %W outputs 0.
Is the Size of a directory the total size of all files inside it?
No. It is the storage size of the directory's own metadata. To check the total space used by files under the directory, use du -sh directory.









