Skip to main content

Crate mtag_cli

Crate mtag_cli 

Source
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-run

Copy files into the target library:

mtag ./Inbox ./Music

Keep 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.mp3

After:

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_artist is preferred for the top-level folder when the tag provides it.
  • If album_artist is 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 .lrc file 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 --open

For 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 --locked

See 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.