The stat Command: Complete Guide to File Metadata Analysis
Introduction
The stat command is a fundamental Unix/Linux utility that displays detailed information about files and file systems. Unlike the basic ls command which provides a summary view, stat offers comprehensive metadata including timestamps, permissions, ownership, file size, inode information, and much more. This command is essential for system administrators, developers, and power users who need to analyze file properties in depth.
Basic Syntax and Usage
The basic syntax of the stat command is:
`bash
stat [OPTION]... FILE...
`
Where:
- [OPTION]... represents optional flags that modify the command's behavior
- FILE... represents one or more files or directories to examine
Simple Example
`bash
stat myfile.txt
`
This command displays all available metadata for the file myfile.txt.
Understanding stat Output
When you run stat on a file, it produces output similar to this:
`
File: myfile.txt
Size: 1024 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Ino: 123456 Links: 1
Access: (0644/-rw-r--r--) Uid: (1000/username) Gid: (1000/groupname)
Access: 2024-01-15 10:30:45.123456789 +0000
Modify: 2024-01-15 10:25:30.987654321 +0000
Change: 2024-01-15 10:25:30.987654321 +0000
Birth: 2024-01-15 10:25:30.987654321 +0000
`
Let's break down each component:
File Information Fields
| Field | Description | Example Value |
|-------|-------------|---------------|
| File | The name of the file being examined | myfile.txt |
| Size | File size in bytes | 1024 |
| Blocks | Number of 512-byte blocks allocated | 8 |
| IO Block | Optimal I/O block size | 4096 |
| File Type | Type of file (regular, directory, link, etc.) | regular file |
| Device | Device ID in hexadecimal and decimal | 801h/2049d |
| Ino | Inode number | 123456 |
| Links | Number of hard links | 1 |
| Access (permissions) | File permissions in octal and symbolic notation | (0644/-rw-r--r--) |
| Uid | User ID and username of owner | (1000/username) |
| Gid | Group ID and group name | (1000/groupname) |
Timestamp Information
The stat command displays three important timestamps:
| Timestamp | Description | When It Changes | |-----------|-------------|-----------------| | Access (atime) | Last time file was accessed/read | When file content is read | | Modify (mtime) | Last time file content was modified | When file content changes | | Change (ctime) | Last time file metadata was changed | When permissions, ownership, or content changes | | Birth | File creation time (if supported by filesystem) | When file is created |
Command Line Options
The stat command supports numerous options to customize its output and behavior:
Display Format Options
| Option | Description | Example Usage |
|--------|-------------|---------------|
| -c, --format=FORMAT | Use custom format | stat -c "%n %s" file.txt |
| -t, --terse | Print information in terse form | stat -t file.txt |
| --printf=FORMAT | Like printf, interpret escape sequences | stat --printf="%n\t%s\n" file.txt |
File System Options
| Option | Description | Example Usage |
|--------|-------------|---------------|
| -f, --file-system | Display file system status | stat -f /home |
| -L, --dereference | Follow symbolic links | stat -L symlink.txt |
Other Options
| Option | Description | Example Usage |
|--------|-------------|---------------|
| --help | Display help information | stat --help |
| --version | Display version information | stat --version |
Format Sequences for Custom Output
The -c or --format option allows you to specify exactly what information to display using format sequences:
File Format Sequences
| Sequence | Description | Example Output |
|----------|-------------|----------------|
| %a | Access rights in octal | 644 |
| %A | Access rights in human readable form | -rw-r--r-- |
| %b | Number of blocks allocated | 8 |
| %B | Size in bytes of each block | 512 |
| %d | Device number in decimal | 2049 |
| %D | Device number in hex | 801 |
| %f | Raw mode in hex | 81a4 |
| %F | File type | regular file |
| %g | Group ID of owner | 1000 |
| %G | Group name of owner | username |
| %h | Number of hard links | 1 |
| %i | Inode number | 123456 |
| %n | File name | myfile.txt |
| %N | Quoted file name with dereference if symbolic link | 'myfile.txt' |
| %o | Optimal I/O transfer size hint | 4096 |
| %s | Total size, in bytes | 1024 |
| %u | User ID of owner | 1000 |
| %U | User name of owner | username |
| %x | Time of last access | 2024-01-15 10:30:45.123456789 +0000 |
| %X | Time of last access as seconds since Epoch | 1705317045 |
| %y | Time of last modification | 2024-01-15 10:25:30.987654321 +0000 |
| %Y | Time of last modification as seconds since Epoch | 1705316730 |
| %z | Time of last change | 2024-01-15 10:25:30.987654321 +0000 |
| %Z | Time of last change as seconds since Epoch | 1705316730 |
File System Format Sequences
When using -f option, different format sequences are available:
| Sequence | Description | Example Output |
|----------|-------------|----------------|
| %a | Free blocks available to non-superuser | 12345678 |
| %b | Total data blocks in file system | 98765432 |
| %c | Total file nodes in file system | 6553600 |
| %d | Free file nodes in file system | 6234567 |
| %f | Free blocks in file system | 13456789 |
| %i | File System ID in hex | 801 |
| %l | Maximum length of filenames | 255 |
| %n | File name | /dev/sda1 |
| %s | Block size | 4096 |
| %S | Fundamental block size | 4096 |
| %t | Type in hex | ef53 |
| %T | Type in human readable form | ext2/ext3 |
Practical Examples
Example 1: Basic File Information
`bash
stat document.pdf
`
Output:
`
File: document.pdf
Size: 524288 Blocks: 1024 IO Block: 4096 regular file
Device: 801h/2049d Ino: 789012 Links: 1
Access: (0644/-rw-r--r--) Uid: (1000/john) Gid: (1000/users)
Access: 2024-01-15 14:22:10.123000000 +0000
Modify: 2024-01-15 14:20:05.456000000 +0000
Change: 2024-01-15 14:20:05.456000000 +0000
Birth: 2024-01-15 14:20:05.456000000 +0000
`
Example 2: Custom Format Output
`bash
stat -c "File: %n, Size: %s bytes, Modified: %y" document.pdf
`
Output:
`
File: document.pdf, Size: 524288 bytes, Modified: 2024-01-15 14:20:05.456000000 +0000
`
Example 3: Multiple Files with Terse Output
`bash
stat -t file1.txt file2.txt file3.txt
`
Output:
`
file1.txt 1024 8 81a4 1000 1000 801 123456 1 0 0 1705316730 1705316730 1705316730 4096
file2.txt 2048 16 81a4 1000 1000 801 123457 1 0 0 1705316800 1705316800 1705316800 4096
file3.txt 512 4 81a4 1000 1000 801 123458 1 0 0 1705316850 1705316850 1705316850 4096
`
Example 4: File System Information
`bash
stat -f /home
`
Output:
`
File: "/home"
ID: 801 0
Namelen: 255 Type: ext2/ext3
Block size: 4096 Fundamental block size: 4096
Blocks: Total: 98765432 Free: 13456789 Available: 12345678
Inodes: Total: 6553600 Free: 6234567
`
Example 5: Following Symbolic Links
`bash
Create a symbolic link
ln -s /etc/passwd mypasswdView link information
stat mypasswdView target file information
stat -L mypasswd`Example 6: Checking File Permissions
`bash
stat -c "Permissions: %a (%A)" /etc/shadow
`
Output:
`
Permissions: 640 (-rw-r-----)
`
Example 7: Monitoring File Changes
`bash
Script to monitor file changes
#!/bin/bash FILE="important.txt" LAST_CHANGE=$(stat -c %Z "$FILE")while true; do
CURRENT_CHANGE=$(stat -c %Z "$FILE")
if [ "$CURRENT_CHANGE" != "$LAST_CHANGE" ]; then
echo "File $FILE was modified at $(stat -c %z "$FILE")"
LAST_CHANGE=$CURRENT_CHANGE
fi
sleep 5
done
`
Advanced Usage Scenarios
Comparing File Timestamps
`bash
Compare modification times of two files
FILE1="version1.txt" FILE2="version2.txt"MTIME1=$(stat -c %Y "$FILE1") MTIME2=$(stat -c %Y "$FILE2")
if [ "$MTIME1" -gt "$MTIME2" ]; then
echo "$FILE1 is newer than $FILE2"
elif [ "$MTIME1" -lt "$MTIME2" ]; then
echo "$FILE2 is newer than $FILE1"
else
echo "Both files have the same modification time"
fi
`
Finding Files by Inode
`bash
Find all files with the same inode (hard links)
INODE=$(stat -c %i myfile.txt) find /path/to/search -inum "$INODE"`Checking File System Space
`bash
Custom file system information display
stat -f -c "Filesystem: %n, Total Space: %b blocks, Free Space: %f blocks, Usage: $((100-100*%f/%b))%" /`Batch Processing Multiple Files
`bash
Display size and modification time for all .log files
for file in *.log; do stat -c "File: %n, Size: %s bytes, Last Modified: %y" "$file" done`Integration with Other Commands
Using stat with find
`bash
Find files modified in the last 24 hours and show detailed info
find /path -type f -mtime -1 -exec stat {} \;`Using stat with sort
`bash
Sort files by size using stat
for file in *; do echo "$(stat -c %s "$file") $file" done | sort -n`Using stat with awk
`bash
Extract and format specific information
stat -c "%n %s %Y" *.txt | awk '{print $1 ": " $2 " bytes, modified " strftime("%Y-%m-%d %H:%M:%S", $3)}'`Troubleshooting and Common Issues
Permission Denied Errors
When stat returns permission denied errors:
`bash
This might fail for system files
stat /etc/shadowSolution: Use sudo
sudo stat /etc/shadow`Non-existent Files
`bash
Check if file exists before running stat
if [ -e "$filename" ]; then stat "$filename" else echo "File $filename does not exist" fi`Symbolic Link Issues
`bash
Broken symbolic link
ln -s /nonexistent/file broken_link stat broken_link # Shows link info stat -L broken_link # Fails because target doesn't exist`Platform Differences
Linux vs macOS/BSD
The stat command varies between GNU/Linux and BSD-based systems:
| Feature | GNU/Linux | macOS/BSD |
|---------|-----------|-----------|
| Format option | -c | -f |
| Terse output | -t | Not available |
| Birth time | %w | %B |
| Default output format | Detailed | Detailed but different |
macOS stat Example
`bash
macOS format for custom output
stat -f "File: %N, Size: %z bytes" filename`Performance Considerations
Efficient stat Usage
`bash
Efficient: Get only needed information
stat -c "%s" large_file.datLess efficient: Get all information when only size is needed
stat large_file.dat | grep Size`Batch Operations
`bash
More efficient for multiple files
stat file1 file2 file3Less efficient
stat file1 stat file2 stat file3`Security Implications
File Permission Analysis
`bash
Check for world-writable files
find /path -type f -exec stat -c "%a %n" {} \; | grep "^[0-9]*[0-9][2367]"`Detecting SUID/SGID Files
`bash
Find SUID files
find /usr -type f -exec stat -c "%a %n" {} \; | grep "^[4567]"`Best Practices
Script Integration
Always check if files exist before using stat in scripts:
`bash
#!/bin/bash
check_file_info() {
local file="$1"
if [ -e "$file" ]; then
echo "File: $file"
stat -c "Size: %s bytes, Permissions: %a, Owner: %U" "$file"
else
echo "Error: File '$file' not found" >&2
return 1
fi
}
`
Error Handling
`bash
Robust stat usage with error handling
get_file_size() { local file="$1" local size if size=$(stat -c %s "$file" 2>/dev/null); then echo "$size" else echo "Error: Cannot access file '$file'" >&2 return 1 fi }`Logging File Changes
`bash
Log file metadata changes
log_file_status() { local file="$1" local logfile="/var/log/file_status.log" { echo "Timestamp: $(date)" stat "$file" echo "---" } >> "$logfile" }`Conclusion
The stat command is an indispensable tool for system administration, file system analysis, and script development. Its ability to provide comprehensive file metadata makes it essential for:
- System monitoring and troubleshooting - Security auditing and permission analysis - Backup and synchronization scripts - File system forensics - Development and debugging
Understanding the various options, format sequences, and practical applications of stat enables users to effectively analyze file systems, monitor changes, and automate system administration tasks. Whether you're a system administrator managing servers, a developer working with file operations, or a power user seeking detailed file information, mastering the stat command will significantly enhance your command-line proficiency and system understanding.
The command's flexibility through custom format strings and its integration capabilities with other Unix tools make it a cornerstone utility in the Unix/Linux ecosystem. Regular practice with different options and scenarios will help you leverage its full potential for various file system analysis tasks.