# musicrename

A CLI tool for normalizing a local music library into a consistent, sanitized
directory hierarchy based on internal metadata tags.

## Installation

**From source:**

```sh
make
sudo make install
```

**Arch Linux (AUR):**

```sh
pacman -S musicrename
```

_(Available from my personal package repository.)_

## Directory Structure

Files are organized as:

```
[first letter]/[artist]/[year] [album]/[track] [title].ext
```

For example:

```
b/beyonce/[2003] dangerously in love/01 crazy in love.flac
0/2pac/[1996] all eyez on me/1-01 ambitionz az a ridah.flac
```

Artist names beginning with a digit or symbol fall under `0/`. If the year tag
is absent the year prefix is omitted. Multi-disc albums include the disc number
in the track filename; single-disc albums do not.

All strings pass through a sanitization pipeline: Unicode transliteration, ASCII
lowercasing, stripping of non-alphanumeric characters, and truncation. A small
set of hardcoded overrides handles known edge cases (e.g. `AC/DC` → `ac⁄dc`).

Each album directory may contain:

| Path                                | Contents                        |
| ----------------------------------- | ------------------------------- |
| `*.flac` / `*.mp3` / `*.m4a`        | Audio files                     |
| `folder.jpg` / `folder.png`         | Primary artwork                 |
| `*.log`, `*.cue`, `*.m3u`, `*.m3u8` | Text assets                     |
| `sums.md5`                          | Checksums (generated by `sums`) |
| `artwork/`                          | Additional images               |
| `scans/`                            | High-resolution scans           |
| `extras/`                           | Everything else                 |

## Workflow

```sh
mrr rename   # move files into the normalized structure
mrr lyrics   # fetch and embed lyrics from LRCLIB
mrr check    # audit for metadata and structural issues
mrr sums     # generate md5 checksums
```

Each command accepts an optional `[path]` argument and defaults to the current
directory. `rename` supports `--dry-run` to preview output without making
changes. `lyrics` and `sums` support `--force` to overwrite existing data.

## Commands

### `rename`

Reads metadata tags and moves files into the normalized hierarchy. Unknown files
(those that don't match any recognized category) are left in place and reported
as warnings. Collisions or overwrite conflicts abort the run immediately.

```sh
mrr rename --dry-run ~/music
```

### `lyrics`

Fetches lyrics from [LRCLIB](https://lrclib.net) and embeds them into audio
tags. Queries by title, artist, album, and duration; progressively relaxes the
duration constraint before falling back to a fuzzy search. Synced (LRC) lyrics
are embedded in FLAC files; unsynced lyrics are embedded in MP3 and M4A.

```sh
mrr lyrics --force ~/music/b/beyonce
```

### `check`

Audits for metadata completeness, album consistency, audio quality tags
(ReplayGain), artwork, missing `sums.md5`, and path conformance. Exits non-zero
if any findings are present, making it suitable for use in scripts. Operates on
a single file, album directory, or library root.

```sh
mrr check ~/music
echo $?   # non-zero if findings
```

### `sums`

Computes MD5 checksums for all files in an album and writes `sums.md5`,
compatible with `md5sum -c`. In library mode, albums that already have a
`sums.md5` are skipped unless `--force` is passed.

```sh
mrr sums ~/music
md5sum -c ~/music/b/beyonce/\[2003\]\ dangerously\ in\ love/sums.md5
```

### `inspect`

Displays raw tag values alongside the sanitized forms that `rename` would use.
Read-only; accepts `.flac`, `.mp3`, and `.m4a` files.

```sh
mrr inspect "01 back in black.flac"
```

## Metadata Notes

- **Album artist:** uses `ALBUMARTIST` tag; falls back to the `ARTIST` tag of
  the lowest-numbered track if absent.
- **Year:** extracted from the `DATE` tag; full ISO-8601 dates and year-month
  values are supported (only the four-character year is used).
- **Disc numbers:** all-or-nothing per album. If any track has a `DISCNUMBER`
  tag, all tracks must have one or the album is skipped with an error.
- **Track numbers:** zero-padded to two digits; switches to three digits if any
  track on the album exceeds 99. A value of `0` is valid (pre-gap track).
- **Sort bucketing:** if the `ALBUMARTISTSORT` tag is present, its first
  character determines the directory bucket (`b/` for "Beatles, The") while the
  folder name still comes from `ALBUMARTIST` ("the beatles").

## Contributing

This is a personal tool but if you stumble across it and find it useful, PRs and
issues are welcome.

## License

```
Copyright © 2020-2026 Mario Finelli

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
```
