Expand description
§mtag-cli
Music Tag Organizer for self-built media libraries such as Plex, Emby, and Jellyfin.
mtag scans a source music folder, reads audio tag metadata, and writes a clean
artist/album folder layout. It is conservative by default: files are copied, existing
destinations cause an error, and --dry-run lets you inspect the plan first.
§Install
Requires Rust 1.95 or newer.
cargo install mtag-cli§Quick Start
Preview the organization plan:
mtag ./Inbox ./Music --dry-runCopy files into the target library:
mtag ./Inbox ./MusicKeep existing files and write duplicates as song (1).mp3, song (2).mp3, and so on:
mtag ./Inbox ./Music --on-conflict rename§Usage
Usage: mtag [OPTIONS] <MUSIC_FOLDER> [TARGET_FOLDER]
Arguments:
<MUSIC_FOLDER> Folder that contains source music files
[TARGET_FOLDER] Folder where organized files will be written [default: Music]
Options:
--dry-run Print planned file operations without writing files
--move Move files instead of copying them
--on-conflict <ON_CONFLICT> How to handle existing destination files [default: fail] [possible values: fail, skip, overwrite, rename]
--template <TEMPLATE> Organization template [default: {album_artist}/{album}/{file_name}]
-h, --help Print help
-V, --version Print version§Example Layout
Before:
Inbox/
compilation/
01 - Hooked On A Feeling.mp3
02 - Go All The Way.mp3
pink-floyd/
101 - In the Flesh.mp3
101 - In the Flesh.lrc
102 - The Thin Ice.mp3
sanitize/
01 - Thunder Test.mp3After:
Music/
AC_DC/
Live_ 2026_/
01 - Thunder Test.mp3
Pink Floyd/
The Wall/
101 - In the Flesh.mp3
101 - In the Flesh.lrc
102 - The Thin Ice.mp3
Various Artists/
Awesome Mix Vol. 1/
01 - Hooked On A Feeling.mp3
02 - Go All The Way.mp3§Organization Rules
album_artistis preferred for the top-level folder when the tag provides it.- If
album_artistis missing, mtag uses the track artist. - If multiple artists share the same album in the same source folder, mtag places that album under
Various Artists. - Same-named albums from different source folders are not merged into
Various Artists. - A same-stem
.lrcfile next to an audio file is copied or moved with that audio file. - Unsafe path characters such as
/,\,:,?, and..are sanitized before folders are created.
§Conflict Policies
Use --on-conflict to choose how existing destination files are handled:
fail Stop with an error. This is the default.
skip Keep the existing destination and skip the new file.
overwrite Replace the existing destination.
rename Keep both files by writing to the next "name (N).ext" path.§Templates
The default template is:
{album_artist}/{album}/{file_name}Supported variables:
{album_artist}
{album}
{artist}
{disc}
{track}
{title}
{file_name}Example:
mtag ./Inbox ./Music --template "{album_artist}/{album}/{track} - {title}.mp3"Each slash-separated template segment is rendered and sanitized as one path component.
§Library API
The crate exposes the CLI pipeline as small Rust modules:
use std::path::Path;
use mtag_cli::{
executor::{execute_plan, ExecutionOptions},
metadata::read_track_metadata,
planner::{build_copy_plan, OrganizationOptions},
scanner::scan_audio_files,
};
let files = scan_audio_files(Path::new("./Inbox"))?;
let tracks = files
.iter()
.map(|path| read_track_metadata(path))
.collect::<Result<Vec<_>, _>>()?;
let plan = build_copy_plan(&tracks, Path::new("./Music"), &OrganizationOptions::default())?;
let summary = execute_plan(&plan, &ExecutionOptions::default())?;
println!("planned: {}", summary.planned);Generate local Rust documentation:
cargo doc --no-deps --openFor stricter documentation checks:
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --locked§Development
Run the same checks used before publishing:
cargo fmt --check
cargo test --all-targets --locked
cargo test --doc --locked
cargo clippy --all-targets --all-features --locked -- -D warnings
cargo package --lockedSee RELEASE.md for the release flow and crates.io publishing requirements.
Modules§
- error
- Error types returned by the library API.
- executor
- File operation execution for prepared copy plans.
- metadata
- Audio tag metadata extraction.
- music_
organizer - Backward-compatible organizer entrypoint retained from the early API.
- planner
- Pure organization planning and path rendering.
- scanner
- Recursive audio file discovery.