File System Operations

File Metadata

std::fs::Metadata represents the filesystem attributes of a file, directory, or symbolic link—including its byte length, entry type (FileType), permissions (Permissions), and modification/access/creation timestamps (SystemTime).

Three Ways to Query Metadata (Symlink-Following vs. Non-Following)

Function / Method Follows Symbolic Links? OS Syscall Equivalent When to Use
fs::metadata(path) Yes (queries the target of a symlink; fails with NotFound on a broken symlink) stat (Unix) / GetFileAttributesEx Inspecting the actual file a path resolves to
fs::symlink_metadata(path) No (queries the symlink entry itself!) lstat (Unix) Detecting symlinks (meta.is_symlink()) or inspecting broken symlinks
file.metadata() Queries the already-open file descriptor fstat (Unix) Avoids path lookup overhead and TOCTOU path races when a File is already open!
Given Symlink: `latest.log -> app-2026.log` (1,024 bytes)

  `fs::metadata("latest.log")`
    +-- Follows symlink to `app-2026.log`:
        `.is_file() == true`, `.is_symlink() == false`, `.len() == 1024`

  `fs::symlink_metadata("latest.log")`
    +-- Inspects symlink entry itself:
        `.is_file() == false`, `.is_symlink() == true`

Key Methods on std::fs::Metadata

Method Return Type Description
.len() u64 Size of the file in bytes
.is_file() bool true if regular file
.is_dir() bool true if directory
.is_symlink() bool true if symbolic link (only possible via fs::symlink_metadata or DirEntry::metadata!)
.file_type() FileType Detailed file type (extensible via std::os::unix::fs::FileTypeExt for sockets/FIFOs/devices)
.permissions() Permissions Read-only flag and OS permission mode
.modified() io::Result<SystemTime> Last modification timestamp (mtime)
.accessed() io::Result<SystemTime> Last access timestamp (atime)
.created() io::Result<SystemTime> Creation / birth timestamp (btime, supported on macOS, Windows, and modern Linux statx)
use std::fs::{self, File};
use std::io::{self, Write};
use std::time::SystemTime;

fn main() -> io::Result<()> {
    let path = std::env::temp_dir().join("rust_ch50_metadata_demo.txt");

    {
        let mut f = File::create(&path)?;
        f.write_all(b"0123456789ABCDEF")?;
        // Query metadata directly on the open file descriptor (`fstat`):
        let fd_meta = f.metadata()?;
        println!("via file.metadata() -> len = {} bytes", fd_meta.len());
    }

    let meta = fs::metadata(&path)?;
    let modified_age = SystemTime::now()
        .duration_since(meta.modified()?)
        .unwrap_or_default();

    println!(
        "is_file: {}, is_dir: {}, is_symlink: {}, modified <= 5s ago: {}",
        meta.is_file(),
        meta.is_dir(),
        meta.is_symlink(),
        modified_age.as_secs() <= 5
    );

    fs::remove_file(&path)?;
    Ok(())
}
via file.metadata() -> len = 16 bytes
is_file: true, is_dir: false, is_symlink: false, modified <= 5s ago: true