When working with files, you often need more than just their contents. File metadata provides crucial information about files: their size, when they were created or modified, what type they are (file, directory, symlink), and their permissions. Rust's std::fs::Metadata struct gives you access to all of this information through a clean, cross-platform API.
The metadata() function (or symlink_metadata() for symlinks) returns a Metadata struct containing information about a file. This is useful for filtering files by size or date, checking permissions before attempting operations, or building file managers and backup tools.
You can obtain metadata using std::fs::metadata() or from a path directly:
use std::fs;
// From a path
let meta = fs::metadata("file.txt")?;
// Check file size in bytes
let size = meta.len();
// Check if it's a file, directory, or symlink
let is_file = meta.is_file();
let is_dir = meta.is_dir();
let file_type = meta.file_type();
// Get modification and access times
let modified = meta.modified()?;
let accessed = meta.accessed()?;The FileType struct tells you what kind of filesystem entry you're dealing with:
let file_type = meta.file_type();
if file_type.is_file() {
println!("Regular file");
} else if file_type.is_dir() {
println!("Directory");
} else if file_type.is_symlink() {
println!("Symbolic link");
}Modification and access times are returned as SystemTime, which you can compare or convert to durations:
use std::time::{SystemTime, Duration};
let modified = meta.modified()?;
let age = SystemTime::now().duration_since(modified)?;
println!("File was modified {} seconds ago", age.as_secs());On Unix systems, you can access file permissions through the PermissionsExt trait:
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
let perms = meta.permissions();
#[cfg(unix)]
{
let mode = perms.mode();
// Check execute bits
let is_executable = mode & 0o111 != 0;
}Implement the following functions to work with file metadata:
get_file_size(path: &Path) -> io::Result<u64>
get_file_type( path: &Path ) -> io::Result<String>
is_readonly(path: &Path) -> io::Result<bool>
get_modified_time( path: &Path ) -> io::Result<SystemTime>
was_modified_within( path: &Path, duration: Duration ) -> io::Result<bool>
is_executable( path: &Path ) -> io::Result<bool>
compare_modified_times( path1: &Path, path2: &Path ) -> io::Result<Ordering>
use std::path::Path;
use std::time::Duration;
use std::cmp::Ordering;
// Get file size
let size = get_file_size(Path::new("data.txt"))?;
assert!(size > 0);
// Check file type
let file_type = get_file_type(Path::new("./src"))?;
assert_eq!(file_type, "directory");
// Check if read-only
let readonly = is_readonly(Path::new("config.txt"))?;
// Get modification time
let modified = get_modified_time(Path::new("file.txt"))?;
// Check if recently modified (within last hour)
let recent = was_modified_within(
Path::new("log.txt"),
Duration::from_secs(3600)
)?;
// Check if executable
let executable = is_executable(Path::new("script.sh"))?;
// Compare modification times
let ordering = compare_modified_times(
Path::new("file1.txt"),
Path::new("file2.txt")
)?;
match ordering {
Ordering::Less => println!("file1 is older"),
Ordering::Greater => println!("file1 is newer"),
Ordering::Equal => println!("Same modification time"),
}std::fs::metadata(path) to get the
Metadata structMetadata::len() returns file size in bytesMetadata::file_type() returns a FileType
with is_file(), is_dir(), is_symlink()
methodsMetadata::permissions() returns a
Permissions struct with readonly() methodMetadata::modified() returns
io::Result<SystemTime> - the modification
timewas_modified_within, use
SystemTime::now().duration_since(modified)
to get elapsed time#[cfg(unix)]
and
std::os::unix::fs::PermissionsExt::mode()mode & 0o111 != 0 (any of owner/group/
other execute).exe, .bat, .cmd) as an alternativeSystemTime implements
PartialOrd so you can compare directly