Rust File Metadata
File metadata is the set of facts a filesystem keeps about a file. fs::metadata reads those facts without opening the file.
Ask about a file
metadata answers size and kind questions at once.
let meta = fs::metadata("note.txt").unwrap();
println!("bytes = {}", meta.len());
println!("is_file = {}", meta.is_file());When did it change?
modified() gives a SystemTime. UNIX_EPOCH turns it into seconds you can read.
let secs = meta.modified().unwrap().duration_since(UNIX_EPOCH).unwrap().as_secs();
println!("changed at unix time {secs}");Rename (move) a file
rename moves the file. The old name stops existing.
fs::rename("note.txt", "moved.txt").unwrap();
println!("moved = {}", Path::new("moved.txt").exists());Copy and count
copy returns how many bytes it duplicated.
let copied = fs::copy("moved.txt", "copy.txt").unwrap();
println!("copied = {copied}");A second name for the same file
fs::hard_link makes a second name for the same contents. Edit through one name. The other name sees the change:
fs::write("orig.txt", "shared words")?;
fs::hard_link("orig.txt", "hard.txt")?;
fs::write("hard.txt", "changed once")?;
println!("via orig = {}", fs::read_to_string("orig.txt")?);A link that points by name
A symlink stores a path as text. That stored path is read from the link's folder. It is not read from yours. This link lives beside its target, so a bare file name is right:
fs::write("real.txt", "real words")?;
std::os::unix::fs::symlink("real.txt", "link.txt")?;
println!("via link = {}", fs::read_to_string("link.txt")?);
println!("stored target = {}", fs::read_link("link.txt")?.display());Example
use std::fs;
use std::path::Path;
fn main() {
fs::write("draft.txt", "hello metadata").unwrap();
let meta = fs::metadata("draft.txt").unwrap();
println!("size = {} bytes", meta.len());
println!("is_file = {}", meta.is_file());
fs::rename("draft.txt", "final.txt").unwrap();
println!("renamed exists = {}", Path::new("final.txt").exists());
println!("old name exists = {}", Path::new("draft.txt").exists());
let copied = fs::copy("final.txt", "backup.txt").unwrap();
println!("copied = {} bytes", copied);
fs::remove_file("final.txt").unwrap();
fs::remove_file("backup.txt").unwrap();
println!("cleaned up = {}", !Path::new("final.txt").exists());
}
Key points
- Use fs::metadata(path) to get a Metadata value.
- len() counts bytes.
- is_file() and is_dir() name the kind.
- All of this works without opening the file.
- Use metadata.modified() to get the last-change time as a SystemTime.
- Compare it with SystemTime::UNIX_EPOCH to work in plain seconds.
- Use fs::rename(from, to) to move a file.
- It also replaces a file that already exists at the destination.
- So renaming is the classic way to update a file atomically.
- Use fs::copy(from, to) to duplicate a file.
- It returns Ok with the number of bytes copied.
- And fs::remove_file deletes a file.
- The Writing Files lesson shows remove_file.
- Use fs::hard_link(from, to) to give one file a second name.
- Both names share the same contents.
- The file itself survives until its last name is removed.
- Use fs::remove_dir(path) to delete one empty folder.
- Use fs::remove_dir_all(path) to delete a folder and everything inside it.
- That call cannot be undone.
- File metadata is the filesystem's facts about a file, such as its size, its kind, and its last-change time.
- fs::symlink_metadata tells you about the link itself.
The closing program writes a 14-byte draft. It reads its size and kind, then renames it. It checks both names and copies it. Then it prints the copied byte count and tidies up.
Note
metadata follows symlinks.
If the path is a link, you learn about the file it points at.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Rust Playground
Exercise
Which call tells you a file's size without opening it?