Files
2026-07-12 10:17:17 -04:00

3.6 KiB

name, description
name description
music-renamer Rename local music files using ID3 tags (mutagen), and optionally manage with beets. For when the user wants to clean up numbered/poorly-named music files using their embedded artist/title metadata.

Music Renamer

Rename music files in-place using embedded ID3 tags. The primary path uses mutagen directly — fast, no network calls, works on any file with good tags. Beets is available as a secondary path for library management but its import step (MusicBrainz matching) is too slow for bulk renames.

Trigger

User asks to rename/organize music files, clean up filenames, strip number prefixes from downloaded music, or set up beets for local music.

Support files

  • scripts/rename_by_tags.py — mutagen-based in-place renamer (run via execute_code)
  • references/beets-config.yaml — minimal beets config for no-move setup

When to use mutagen vs beets

Scenario Tool
Files already have good ID3 tags, just need renaming mutagen (scripts/rename_by_tags.py)
Files have NO tags, need to be matched against MusicBrainz beets import (with autotag)
Need full library management / queries / stats beets
Small batch (< 50 files) needing autotag beets import is fine
Large batch (> 100 files) mutagen — beets import will time out

Step 1 — Determine scope

CRITICAL: Confirm which directories the user wants renamed. Never assume "all music." If they say "just the Albanian folder," do NOT touch English or other folders. Use find with a -regex pattern to count files with number prefixes to identify what's unrenamed:

find /path/to/music -type f -regex ".*/[0-9]+\. .*"

Files with number prefixes (e.g., 123. Title.mp3) are the unrenamed ones. Files already in Artist - Title.ext format are done.

Step 2 — Run the rename script

Use scripts/rename_by_tags.py (copy the code from execute_code — it uses mutagen via the same Python environment). The script:

  • Walks a base directory recursively
  • Reads artist/title from ID3 tags via mutagen
  • Renames files to Artist - Title.ext in-place (same directory)
  • Skips files already in the correct format
  • Handles collisions by appending (1), (2) etc.
  • Handles slashes in artist/title by replacing with -

Key code pattern:

from mutagen import File
audio = File(fullpath, easy=True)
artist = audio.tags.get('artist', [None])[0]
title = audio.tags.get('title', [None])[0]
new_name = f"{artist} - {title}".replace('/', '-') + ext

Step 3 — Verify

Check a few directories to confirm the rename:

ls /path/to/music/some-folder/ | head -10
find /path/to/music -regex ".*/[0-9]+\. .*" | wc -l  # should be 0

Beets config (fallback)

Beets config lives at ~/.config/beets/config.yaml. Minial config for in-place (no-move) setup:

directory: /path/to/music
library: /path/to/music/musiclibrary.db

import:
    copy: no
    move: no
    write: yes
    quiet: yes

paths:
    singleton: %(artist)s - %(title)s
    comp: Compilations/%(album)s/%(artist)s - %(title)s

Known pitfalls with beets

  • beet import without -A hits MusicBrainz for every file — very slow for 100+ files, will time out
  • beet import -A -q --singletons still slow for 1000+ files due to per-file overhead
  • beet move uses directory + path_template — cannot rename truly in-place within subdirectories
  • Only use beets for library management / queries, not bulk renames

User preferences

  • Ray prefers mutagen over beets for bulk renaming
  • Always confirm directory scope — don't expand beyond what was asked