Skip to content

Scripts to keep your music collection tidy. Extract from a ZIP, review and fix metadata… Designed with Bandcamp and Amazon Music in mind, but works with pretty much any ZIP archive that contains MP3 or FLAC files.

alice-mm/bandcampetc

Repository files navigation

Bandcamp, etc. (bandcampetc)

Scripts to keep music tidy.

The main script (bandcamp) can be used to extract and clean files (allow to review and easily edit some metadata fields) from Bandcamp and Amazon Music downloads. The files are then stored in a configurable location, in neatly named directories. It should work with pretty much any ZIP archive that contains MP3 or FLAC files. See example below.

Some other scripts, here, are dependencies of the bandcamp one, but can also be used on their own for various purposes.

I don’t do proper releases nor use tags at the moment, but I try to keep master fairly stable. Ping me if you think I screwed up somewhere.

Getting started

Execution

  1. Download the project and save it where it suits you.

  2. Add the bin/ directory to your PATH to be able to run these scripts from anywhere.

~/.bashrc
PATH+=':~/bin/bandcampetc/bin/'
export PATH
Warning

Make sure you adapt the ~/bin/bandcampetc/bin/ path of the example according to where you saved this project.

Dependencies

The bandcamp script relies on:

Bash · version ≥ 4.3

Because associative arrays and variables declared with -n. Should already be OK on most machines.

eyeD3

Manipulate MP3 metadata. Note that the software’s package is generally called eyed3. These guys often break backward compatibility… I adapted my commands firstly to version 0.6.18 (Ubuntu 16) and later to 0.7.10 (Debian 9). Tell me if you get “unrecognized arguments” errors.

metaflac

Manipulate FLAC metadata. Bundled with the flac package.

rsync

“A fast, versatile, remote (and local) file-copying tool.”

unzip

Decompress ZIP archives.

ImageMagick

To manipulate cover art. (imagemagick package.)

awk

“Pattern scanning and processing language.” GNU’s gawk implementation recommended, but the minimal implementation mawk does the job.

geany

… as a recommended simple text editor to revise music metadata. You can use any other editor by changing a constant’s value in config/bandcamp.sh.

ffmpeg or avconv

For FLAC → MP3 conversions.
(Optional, see the config section.)

file

Installed on most distributions, but missing from some Docker images. The package is also called file.

curl · version ≥ 7.67.0

To send HTTP requests to the MusicBrainz API.
(Optional, for the getgenre script.)

jq

To process the data sent back by the MusicBrainz API. Version 1.6 is recommended, but it may work with older ones.
(Optional, for the getgenre script.)

Tip

On Ubuntu and Debian machines, this should be enough to get everything:

$ sudo apt install eyed3 flac rsync unzip imagemagick gawk geany ffmpeg file jq curl

Contents

bandcamp

The main script, at least from my point of view. When you download music from Bandcamp, Amazon Music, etc., you generally end up with a random ZIP archive full of poorly named files. Furthermore, the music’s metadata is often dirty as well: some labels add random information (sometimes even catalogue numbers!) in the tracks’ titles and so on.

This script can be run from anywhere (it has no importance) without argument.

  1. It will look for ZIPs in ~/Downloads/, ~/Téléchargements/, ~/Descargas/, ~/Загрузки/… You can also give ZIPs directly as arguments to the script.

  2. For each ZIP that contains MP3 or FLAC files, the files will be extracted.

  3. You will be offered the possibility to edit the music’s metadata in a text editor.

  4. The files will be tagged and named according to the cleaned version of the metadata.

  5. If the album is in FLAC format and if the CONVERT_TO_MP3 constant has been set to a non-empty value, an MP3 version of the record will be generated alongside the FLAC version.

  6. The original ZIP will be discarded.

See bandcamp -h for help.

capitasong

Try to put capital letters in nice places in song and record titles. This is not perfect, of course, but this script provides a good starting point for metadata cleaning. As time went by, this also became a utility to clean up some common ugly things that have little or even nothing to do with capitalization.

  $ capitasong "You will blow up a dog some day, as the other guy said"
You Will Blow Up a Dog Some Day, as the Other Guy Said

  $ capitasong "Le chien de ta mère est gros"
Le Chien de Ta Mère Est Gros
Note

Many conventions exist. I used stuff from http://aitech.ac.jp/~ckelly/midi/help/caps.html. (That weird link might become dead or point to something unrelated someday. Use with caution.)

getgenre

Try to get a musical genre from tags found on MusicBrainz. Can try to target a specific release or (on purpose or as a fallback) an artist itself.

By default, only the best tag is printed out, but -n, --number can be used to ask for more. In such cases, the best tags will come first.

Example 1. Sample calls
Specific album, two results
  $ getgenre -a 'sigur ros' -r kveikur -n 2
Post-rock
Rock
Artist as a whole, single result, long option name
  $ getgenre --artist 'negura bunget'
Black metal
Getting help
$ getgenre -h

covers

Try to fetch cover arts from various sources. An old ugly script of mine. Don’t pay it too much attention. Most album downloads already contain a cover anyway, so this is seldom called. This may break as the used websites change their APIs or page layout, etc.

Warning

Since Bandcamp albums always contain a cover art already, I don’t devote time to the covers script. It can still fetch stuff from Wikipedia (which can lead to some surprises, for better or for worse), but that’s about it. See also #41.

I encourage you to manually add a cover.jpg file to ZIPs that come from somewhere else than Bandcamp, so that the main script will grab that and call it a day.

setcover

I like to add the cover art in the music files’ metadata. This way, even devices such as cars with no Internet access or whatever are able to display cover arts when playing music. The setcover script embed a cover art in MP3 and FLAC files. See setcover -h for help.

create-lq-cover

To prevent art addition (see setcover) from making my files oversized, I use a low-quality version of it. The create-lq-cover script simply creates lightweight pictures from a given original version.

mmeta

Used to be able to display metadata from MP3 and FLAC files using the same command. This uses homemade pattern strings.

  $ mmeta '\n%f\n%a, “%t” [%l, %s]\n\t(“%A”, %y, %g)\n\n' ./{salvation,eternal_kingdom/*}/1*

./salvation/1_-_echoes.mp3
Cult of Luna, “Echoes” [59:09, 13.50 MB]
<TAB>(“Salvation”, 2004, Post-Metal)


./eternal_kingdom/flac/10_-_following_betulas.flac
Cult of Luna, “Following Betulas” [Unknown, Unknown]
<TAB>(“Eternal Kingdom”, 2008, Post-metal)

See mmeta -h for help.

to_acceptable_name

I love this one. It eats a string and gives a version of it devoid of weird characters. I use it to rename all my music files. Since I buy obscure black metal and stuff, I had to update it to roughly transliterate Cyrillic and Icelandic. It still can’t handle Japanese properly, though. Sorry.

    $ to_acceptable_name <<< "@Œӂ (%s/) «¼___.flac"
atoez_s_1_4.flac

    $ to_acceptable_name <<< '円423 for you.MP3'
423_yens_for_you.mp3
Tip

This script also cuts long file names to 255 characters to avoid errors, while trying to keep the file’s extension.

give_acceptable_name

Use to_acceptable_name to find a suitable name for a file, and rename that file using that name.

Tip

I like to add this as a custom action in my file manager. Typically, in Thunar:

give_acceptable_name %F

(“Edit” → “Configure custom actions…”)

Remember to check that the “Appearance Conditions” are broad enough.

Configuration of the bandcamp script

Various settings can be changed in the config/bandcamp.sh file.

Converting FLAC files to MP3s

To get both a FLAC and an MP3 version of your records, check the part of config/bandcamp.sh that looks like this:

CONVERT_TO_MP3=''

To turn the feature on, change this line to:

CONVERT_TO_MP3=1
Tip

To activate conversion for one specific run, you can use the -c option:

$ bandcamp -c

Editor

To choose the text editor used to edit music metadata, check the part of config/bandcamp.sh that looks like this:

unset -v EDITOR
#readonly EDITOR=(nano -S)
#readonly EDITOR=(vi)
#readonly EDITOR=(mousepad)
#readonly EDITOR=(leafpad)
#readonly EDITOR=(gedit)
#readonly EDITOR=(code --new-window --wait)
readonly EDITOR=(geany -i)

The commented out lines give you examples for other editors than Geany. Uncomment one of them (while commenting the others), or write your own assignment.

Note

I use an indexed array rather than a dumb string to make the script more robust: you can use parameters that contain spaces: readonly EDITOR=(foo -f 'bar plop' -M)

Tip

To make the script run without any interaction, use a no-op or any idle-ish command as an editor: readonly EDITOR=(:)

Caution

The editor must block the execution flow, so that you’re able to edit the metadata, save, and close it before the rest of the script runs. Some editors, like Visual Studio Code, tend to launch themselves in the background – much like when appending & to a command – on their own, and may require tweaks to be used properly in this context. Some have options to avoid this: use code --wait instead of just code for Visual Studio Code and you should be OK.

Tests

Unit tests

I love trying to do unit testing in Bash. Just run ./run_tests.sh and a bunch of commands will be executed. The first failure stops the execution (set -e) and you should be able to see what failed in the output.

If everything works as intended, the output should end with a message like:

run_tests.sh: All done (22 files).
Tip

For development purposes, you can run a subset of the test scripts by passing them as arguments:

$ ./run_tests.sh test_scripts/mmeta.sh test_scripts/setcover/gettype.sh

Integration tests

The run_integration_tests.sh script runs the unit tests as well as the bandcamp script in a Debian Docker container. Nothing fancy for now as I’m no Docker expert, but it allowed me to improve stuff already.

Sample execution of bandcamp

(Kinda old; may not reflect perfectly the latest version’s logs.)

With one ZIP from https://giftsfromenola.bandcamp.com/album/from-fathoms in ~/Downloads/:

  $ bandcamp
bandcamp: Inspecting “/home/alice/Downloads/Gifts From Enola - From Fathoms.zip”...
Archive:  ./Gifts From Enola - From Fathoms.zip
 extracting: Gifts From Enola - From Fathoms - 01 Benthos.flac
 extracting: Gifts From Enola - From Fathoms - 02 Weightless Frame.flac
 extracting: Gifts From Enola - From Fathoms - 03 Weightless Thought.flac
 extracting: Gifts From Enola - From Fathoms - 04 Trieste.flac
 extracting: Gifts From Enola - From Fathoms - 05 Resurface.flac
 extracting: Gifts From Enola - From Fathoms - 06 Melted Wings.flac
 extracting: Gifts From Enola - From Fathoms - 07 Thawed Horizon.flac
 extracting: Gifts From Enola - From Fathoms - 08 Aves.flac
 extracting: cover.jpg

  ╭────────────────────────────────────────────╌╌┄┄┈┈
  │ Type:    flac
  │ Artist:  Gifts from Enola
  │ Album:   “From Fathoms”
  ╰────────────────────────────────────────────╌╌┄┄┈┈

  [Here, my editor was launched and I set the genre as “Post-rock” before closing it.]

bandcamp: Track 1 of 8...
bandcamp: Track 2 of 8...
bandcamp: Track 3 of 8...
bandcamp: Track 4 of 8...
bandcamp: Track 5 of 8...
bandcamp: Track 6 of 8...
bandcamp: Track 7 of 8...
bandcamp: Track 8 of 8...
bandcamp: Found cover: cover.jpg
 HQ → “cover.jpg” (3,5M)
 LQ → “./cover_lq.jpg” (resize: 512×512; quality: 85) (112K)
'cover.jpg' -> 'gifts_from_enola/from_fathoms/flac/cover.jpg'
'cover_lq.jpg' -> 'gifts_from_enola/from_fathoms/flac/cover_lq.jpg'
removed 'cover.jpg'
removed 'cover_lq.jpg'
bandcamp: Applying “gifts_from_enola/from_fathoms/flac/cover_lq.jpg” to files...
bandcamp: Renaming files...
 “Gifts From Enola - From Fathoms - 01 Benthos.flac” → “1_-_benthos.flac”
 “Gifts From Enola - From Fathoms - 02 Weightless Frame.flac” → “2_-_weightless_frame.flac”
 “Gifts From Enola - From Fathoms - 03 Weightless Thought.flac” → “3_-_weightless_thought.flac”
 “Gifts From Enola - From Fathoms - 04 Trieste.flac” → “4_-_trieste.flac”
 “Gifts From Enola - From Fathoms - 05 Resurface.flac” → “5_-_resurface.flac”
 “Gifts From Enola - From Fathoms - 06 Melted Wings.flac” → “6_-_melted_wings.flac”
 “Gifts From Enola - From Fathoms - 07 Thawed Horizon.flac” → “7_-_thawed_horizon.flac”
 “Gifts From Enola - From Fathoms - 08 Aves.flac” → “8_-_aves.flac”
bandcamp: Moving the files to “/home/alice/Music/gifts_from_enola/from_fathoms“...
bandcamp: All done for this ZIP.
removed '/home/alice/Downloads/Gifts From Enola - From Fathoms.zip'

bandcamp: End.

    $ tree ~/Music/gifts_from_enola/
/home/alice/Music/gifts_from_enola/
└── from_fathoms
    └── flac
        ├── 1_-_benthos.flac
        ├── 2_-_weightless_frame.flac
        ├── 3_-_weightless_thought.flac
        ├── 4_-_trieste.flac
        ├── 5_-_resurface.flac
        ├── 6_-_melted_wings.flac
        ├── 7_-_thawed_horizon.flac
        ├── 8_-_aves.flac
        ├── cover.jpg
        └── cover_lq.jpg

2 directories, 10 files

Contact

If you want to show your appreciation or make suggestions…

Contact email

(You can also send me Bandcamp gifts, I guess, hehe.)

About

Scripts to keep your music collection tidy. Extract from a ZIP, review and fix metadata… Designed with Bandcamp and Amazon Music in mind, but works with pretty much any ZIP archive that contains MP3 or FLAC files.

Topics

Resources

Stars

Watchers

Forks