Ramblings of an aging IT geek
← Ramblings of an aging IT geek
rust

i wrote a 200-line tool in rust to avoid a 20-line shell script

Reflecting on whether rewriting a small personal CLI tool in Rust was a sensible use of time or just an excuse to learn the borrow checker.

A code editor open with a terminal beside it

I had a shell script. It scanned a directory of photos, read a bit of EXIF, and renamed them into a date-based folder structure. Twenty lines, worked fine, had worked fine for two years. So naturally I spent a weekend rewriting it in Rust, and the only honest question afterwards is whether that was worth it.

The script's actual sin was that it was slow and a bit fragile. It shelled out to exiftool once per file, which meant a fresh process for every photo, and on a few thousand images that adds up to minutes. It also handled filenames with spaces and odd characters with the usual shell desperation: lots of quoting, the occasional IFS incantation, and a quiet prayer. It never quite broke, but I never quite trusted it either.

use anyhow::Result;
use structopt::StructOpt;

#[derive(StructOpt)]
struct Opt {
    #[structopt(parse(from_os_str))]
    source: std::path::PathBuf,
}

Rust made two of those problems disappear and one of them worse. The performance was a clear win: reading EXIF in-process with a crate rather than forking exiftool thousands of times took the whole run from minutes to under a second. Filename handling was the other win. PathBuf and OsStr mean the awkward cases that make shell scripts nervous are just the normal path the type system walks you down, so the spaces and the unicode and the missing extensions all got handled because the compiler wouldn't let me not handle them.

The cost was time, and I won't pretend otherwise. The borrow checker and I had a few frank exchanges, mostly about me wanting to hold a reference to something I'd just moved. The error handling, even with anyhow smoothing it over, is more ceremony than a shell script's "ignore everything and hope". A twenty-line script became two hundred lines of Rust, and most of that hour-for-hour difference bought me robustness I didn't strictly need for a personal tool that runs on my own photos.

So was it worth it? For this specific job, on pure cost-benefit, probably not. The shell script would have limped along fine. But I didn't really do it for the photos. I did it because I wanted a small, real, finishable problem to learn Rust on, and "rewrite the thing you already understand" is a genuinely good way to learn a language. You're not fighting the problem and the language at once. You already know what correct looks like, so every fight is purely with the tool.

The tool is faster, sturdier, and I trust it now. The two hours were tuition, not engineering. And the next small thing I reach for, I'll reach for Rust a little sooner, which is the actual return on the weekend.