I had a shell script. It walked a directory of log files, parsed out a timestamp from each filename, and moved anything older than a fortnight into an archive tree. It worked, mostly, until a filename had a space in it, or the date format drifted, or someone ran it twice and the second pass tripped over the first. Every time it broke I patched it with another layer of `` and quoting, and every patch made it harder to read.
So I rewrote it in Rust. Not because it needed to be fast, it ran once a day and finished in under a second either way, but because I wanted the thing to either work or tell me precisely why it didn't.
The win was the parsing. In bash the date came out of a sed incantation that I could no longer fully explain to myself. In Rust it became a function with a return type that said, plainly, this can fail, and here is the failure.
fn parse_log_date(name: &str) -> Result<NaiveDate, ParseError> {
let stamp = name
.strip_suffix(".log")
.and_then(|s| s.rsplit('-').next())
.ok_or(ParseError::NoStamp)?;
NaiveDate::parse_from_str(stamp, "%Y%m%d")
.map_err(|_| ParseError::BadStamp(stamp.to_string()))
}
The compiler made me handle the case where the filename didn't match the pattern at all, which is exactly the case my shell script ignored and then crashed on. Result everywhere is tedious until the day it saves you, and then you forgive it everything.
Was it worth it? Honestly, the rewrite took an afternoon, and the original script would have limped on for years. If you're measuring purely in time saved, no. But the new version has handled six weeks of logs without a single surprise, and I haven't had to think about it once. The shell version demanded attention every fortnight or so. Quiet code has a value that doesn't show up in a stopwatch.
The bits I'd flag if you're tempted to do the same. The binary is a few megabytes where the script was a few hundred bytes, and cargo build is not instant. For a one-off you'll never touch again, that's a poor trade. For a thing that runs on a schedule and must not fail silently, the trade is good. The error messages alone earned their keep: when a colleague dropped a misnamed file in the directory, the tool said BadStamp("notadate") and carried on with the rest, instead of mangling the lot.
I'm not going to rewrite all my scripts in Rust. Most of them are five lines and will never grow. But the ones that have crossed the line from "small glue" into "thing I rely on and dread editing" are good candidates. This was one of them, and it's nice to have it off the list.