Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

Shell alias: hide-song

I have a number of music albums in their entirety: I am a completionist! But that doesn't mean I like every song in the album. Rather than delete those bits, I set them aside. Gzipping alone isn't enough because vlc is smart enough to still play the audio. So I base64 them, and then gzip them (and then sink them into the swamp).

And then I wrote a shell function to do this for me, preserving timestamp. I like metadata; I don't like data.

hide-song() { _i="${1}" ; test ! -f "${_i}" && return 1 ; <"${_i}" base64 >"${_i%%.mp3}.b64" && touch --reference "${_i}" "${_i%%.mp3}.b64" && gzip "${_i%%.mp3}.b64" && \rm "${_i}" ; }
unhide-song() { _i="${1}" ; gunzip "${_i}" && <"${_i%%.gz}" base64 -d > "${_i%%.b64.gz}.mp3" && touch --reference "${_i%%.gz}" "${_i%%.b64.gz}.mp3" && \rm "${_i%%.gz}" ; }

Because I need more word-count, let's explain these.

hide-song() {
    _i="${1}"
    test ! -f "${_i}" && return 1
    <"${_i}" base64 >"${_i%%.mp3}.b64" && \
        touch --reference "${_i}" "${_i%%.mp3}.b64" && \
        gzip "${_i%%.mp3}.b64" && \
        \rm "${_i}"
}

Line 2 sets a variable, and notably not a bash local variable, but I like to use a single underscore to help avoid collisions. I like to avoid bashisms, never mind this is in my bash profile.

Line 3 fails quietly but with an error code. Maybe it should throw a warning. I suppose the -f makes sure it is a real file, and not a symlink and not a directory so it's pulling double duty.

Line 4 base64s the file to file.b64. And yes, I'm anticipating the file has a .mp3 extension. Adapt to your own needs, detail-oriented people!

Line 5 sets the timestamp of the new file to match the original file. (Yes, I don't like bashisms, but GNUisms are perfectly acceptable.)

Line 6 gzips file.b64, which notably preserves the timestamp in my GNU userland. I hardly use gzip without tar, but I guess I do here.

Line 7 deletes the original file. Note the leading slash to avoid any aliases and just run rm. And of course note that the rm happens only if the preceding commands are all successful (&& being the logical and).

Comments