Simon Willison’s Weblog

Subscribe

f2 (via) Really neat CLI tool for bulk renaming of files and directories by Ayooluwa Isaiah, written in Go and designed to work cross-platform.

There's a lot of great design in this. Basic usage is intuitive - here's how to rename all .svg files to .tmp.svg in the current directory:

f2 -f '.svg' -r '.tmp.svg' path/to/dir

f2 defaults to a dry run which looks like this:

*————————————————————*————————————————————————*————————*
|      ORIGINAL      |        RENAMED         | STATUS |
*————————————————————*————————————————————————*————————*
| claude-pelican.svg | claude-pelican.tmp.svg | ok     |
| gemini-pelican.svg | gemini-pelican.tmp.svg | ok     |
*————————————————————*————————————————————————*————————*
dry run: commit the above changes with the -x/--exec flag

Running -x executes the rename.

The really cool stuff is the advanced features - Ayooluwa has thought of everything. The EXIF integration is particularly clevel - here's an example from the advanced tutorial which renames a library of photos to use their EXIF creation date as part of the file path:

f2 -r '{x.cdt.YYYY}/{x.cdt.MM}-{x.cdt.MMM}/{x.cdt.YYYY}-{x.cdt.MM}-{x.cdt.DD}/{f}{ext}' -R

The -R flag means "recursive". The small -r uses variable syntax for EXIF data. There are plenty of others too, including hash variables that use the hash of the file contents.

Installation notes

I had Go 1.23.2 installed on my Mac via Homebrew. I ran this:

go install github.com/ayoisaiah/f2/v2/cmd/f2@latest

And got an error:

requires go >= 1.24.2 (running go 1.23.2; GOTOOLCHAIN=local)

So I upgraded Go using Homebrew:

brew upgrade go

Which took me to 1.24.3 - then the go install command worked. It put the binary in ~/go/bin/f2.

There's also an npm package, similar to the pattern I wrote about a while ago of people Bundling binary tools in Python wheels.