Managing My Music Library with beets
The documentation of the Tangara reminded me to check out a tool that has been collecting dust in my bookmarks for months: the powerful beets!
What a mighty tool! You can have a look at my configuration that takes care of all my music library management needs:
- Clean up tags with data from MusicBrainz (that is beets’ main proposition, no configuration needed for that)
- Properly name and organize files
- Replace special characters in files
- Fetch and embed cover art
- Delete certain ID3 fields
- Automatically convert lossless music files to 320 kbps MP3s on import (Yeah, I know. That topic alone deserves its own note. Short version: I am pretty sure that I’m not capable of noticing the quality differences and rather pick the less storage-hungry but more ubiquitous format.)
- Identify duplicates
And that does not even cover the superb command line interface, beets’ query language, and the vast plugin ecosystem.
The query language allows me to do some neat data analysis on my music collection on the command line. For example, a little bar chart of the number of albums per year (with the help of Zach Holman’s spark):
beet ls -af '$year' | sort | uniq -c | cut -c -7 | xargs | spark
▁▁▁▁▁▁▁▁▁▃▃▃▂▃▄▃▅▆▆▇█▇▅▅▅▂▃▃▃▃▃▆▆▂
I will do mor extensive analysis once my whole collection is managed by beets.
Sync Library With Rsync
I have been thinking about a way to automatically sync my music library whenever I put my Tangara’s SD card into my machine. First I thought that beets
’ own move
command with the export option -e
would be the answer, but unfortunately beets
does not ignore already present files but repeatedly copies them with an incremental suffix leading to loads of duplicates. So I turned to rsync
which is actually built for tasks like this. Let’s have a look at the command that I put together and dissect it:
rsync -vahm --size-only --include='*.mp3' --include='*/' --exclude='*' --delete --delete-excluded <path_to_music_library> <path_to_external_storage>
-v
makes the output ofrsync
a bit more verbose. I like to know what is going on. Extra tip:-i
helped me understand why some files got copied over repeatedly.-a
stands for archive mode which groups several options together, most notably-r
for recursing into directories.-h
for human-readable sizes.-m
prunes empty directories which can happen when you exclude/include certain files like I do in the following.--include
/--exclude
works in a bit of a funny way withrsync
. Including something does not automatically mean that everything else is excluded and you have to consider both files and directories. So what these options are saying is: include*.mp3
files, include all directores, exclude everything else that got not matched by the two include rules that take precedence by order. This can lead to emtpy directories (e.g. when an album consists only of*.flac
files) which is why I added the-m
option.--delete
deletes any extraneous files on the receiver side. That means should I ever rename or reorganize files (which will happen since not all of my music is handled by beets yet) the music library on external storage perfectly mirrors the current state.--delete-excluded
makes sure that newly excluded files are retroactively deleted.
By using rsync
I learned that the Linux FAT driver (and Windows) have issues with files and directories that end with a dot. Directories with a dot at the end—like Papa Roach’s F.E.A.R. album—get copied by rsync
over and over again irrespective of its existence at the destination folder. This StackExchange answer explains what is going on.
I changed my beets replace rules to trim trailing dots and now everything works smoothly. I love small, sharp command-line tools!