in a world where no one cares

Put guards on your destructive operations

tl;dr: Sanity-checking your input should go beyond making sure the input is acceptable. Try to predict contextually-likely mistakes your user will make (even – especially! – when your user is you) and prevent them, particularly when your operation is destructive.

I’m back on a macOS machine more of the time again, which means I’m using (nΓ©e iTunes) more again. It’s not my favourite, but I don’t hate it. (Actually, I normally use Plexamp, but my Plex server is offline at the moment – long story.) My biggest frustration with has always been the lack of native FLAC support, which prevents me from simply network-mounting my music library from my file server and playing it back directly. I used to use Max to batch-convert FLAC to MP4-ensconced AAC (.m4a), because CoreAudio has about the best AAC encoder going, and afconvert is too inscrutable to use directly. But these days, FFmpeg’s native encoder is good enough, so I wrote a simple shell script to:

  • find all FLAC files under the current directory and – in parallel – use FFmpeg to convert them all to AAC-in-MP4;
  • find all M4A files under the current directory and use AtomicParsley to populate their album art from an artwork file in the same directory;
  • delete all non-M4A files under the current directory;
  • add everything left under the current directory into my library (by moving it into ~/Music/Music/Media.localized/Automatically Add to Music.localized/).

If those last two steps haven’t already set off alarm bells in your head, they should’ve! That’s some pretty destructive stuff, particularly because:

  • I’m applying it to the current directory, not some fixed β€œingest” directory, and
  • this script probably lives somewhere in my $PATH, so I can invoke it (maybe accidentally) from anywhere.

In fact, I have accidentally invoked it, from my Downloads directory (which contains nothing of consequence), and from my home directory (which contains approximately everything of value stored locally on my machine). But: I didn’t lose any data in either instance. Why? Because I thought ahead, and added two preconditions to the conversion script:

  1. No files are permitted in the immediate working directory. When I convert music, I do so album by album, not collections of loose files, and those albums are always in their own directories. E.g., I’m always working from a structure like this:
    ./Casualties of Cool/Casualties of Cool (2014)
    ./Casualties of Cool/Casualties of Cool (2014)/CD 1
    ./Casualties of Cool/Casualties of Cool (2014)/CD 1/01 - Daddy.flac
    ./Casualties of Cool/Casualties of Cool (2014)/CD 1/02 - ...
    So a stray file at the top level of the working directory is distinctly abnormal, and might mean that I’m in the wrong place.
  2. The number of FLAC files (files with names ending in .flac) contained within the working directory must exceed the number of all other files.

These checks take more space in the script than the actual conversion work (15 lines vs. 4). And they’re totally worth it.

Write a Comment