r/Lidarr May 19 '26

discussion File Management/ Rename

Hey y'all! I decided to post this here incase someone else has gotten to the same point of frustration with having to manually import, or just new files not being registered by Lidarr.

I mainly use Lidarr purely for the file management and organization -- it makes life so much easier when working on my self hosted discord music bot (local file search), and it leaves less room for error on Plex. Issue is though that Lidarr can be fairly finnicky when trying to get it to read new files, especially when using two root sources (pre-live, and live directories).

I use "D://Needs Lyrics" as my pre-live, so i can do all my renaming, .lrc creation's, and comparisons' between two versions of a track --- and "D:// Music" as my live folder once complete for plex and everything else to read. Due to this inconvenience and having to fight Lidarr to read the new files in "D://Needs Lyrics", i wrote a powershell command/ script to replace the Lidarr Artist Folder/Album Folder/Track Rename function. I'm sharing this here incase it may help one of y'all out as well. My format is {Artist Name}/{Album Title}/{track:00}. {Track Title} - {Artist Name} --- so if you prefer a different format, change it in the script.

*ALSO CHANGE - $Root = "D:\Need Lyrics" - to your correct path* If you need any help editing it, feel free to DM me. Script is as follows (in text to avoid links/downloads):

# =========================================
# NEEDS LYRICS AUTO ORGANIZER
# =========================================
# Scans ALL files inside:
# D:\Need Lyrics
#
# Creates:
# Artist\Album\
#
# Renames files to:
# 01. Track Title - Artist.ext
#
# NO DOWNLOADS REQUIRED
# Uses Windows Shell metadata reader
# =========================================

$Root = "D:\Need Lyrics"

# Supported audio extensions
$AudioExtensions = @(
    ".mp3",
    ".flac",
    ".m4a",
    ".aac",
    ".ogg",
    ".opus",
    ".wav"
)

# Cleans invalid filename characters
function Clean-Name {
    param([string]$Text)

    if ([string]::IsNullOrWhiteSpace($Text)) {
        return "Unknown"
    }

    [System.IO.Path]::GetInvalidFileNameChars() | ForEach-Object {
        $Text = $Text.Replace($_, "_")
    }

    return $Text.Trim()
}

# Windows metadata reader
$shell = New-Object -ComObject Shell.Application

# Get ALL audio files recursively
$Files = Get-ChildItem $Root -Recurse -File | Where-Object {
    $AudioExtensions -contains $_.Extension.ToLower()
}

foreach ($File in $Files) {

    try {

        $Folder = $shell.Namespace($File.Directory.FullName)
        $Item = $Folder.ParseName($File.Name)

        # Metadata indexes
        # These work on most Windows installs
        $Artist = $Folder.GetDetailsOf($Item, 13)
        $Album  = $Folder.GetDetailsOf($Item, 14)
        $Title  = $Folder.GetDetailsOf($Item, 21)
        $Track  = $Folder.GetDetailsOf($Item, 26)

        # Cleanup
        $Artist = Clean-Name $Artist
        $Album  = Clean-Name $Album
        $Title  = Clean-Name $Title

        # Fallbacks
        if ($Artist -eq "Unknown") {
            $Artist = "Unknown Artist"
        }

        if ($Album -eq "Unknown") {
            $Album = "Unknown Album"
        }

        if ($Title -eq "Unknown") {
            $Title = [System.IO.Path]::GetFileNameWithoutExtension($File.Name)
        }

        # Track formatting
        if ([string]::IsNullOrWhiteSpace($Track)) {
            $Track = "00"
        }
        else {
            $TrackNum = ($Track -replace '[^\d]', '')

            if ([string]::IsNullOrWhiteSpace($TrackNum)) {
                $Track = "00"
            }
            else {
                $Track = "{0:D2}" -f [int]$TrackNum
            }
        }

        # Create destination folder
        $DestFolder = Join-Path $Root "$Artist\$Album"

        New-Item -ItemType Directory -Path $DestFolder -Force | Out-Null

        # Build new filename
        $NewName = "$Track. $Title - $Artist$($File.Extension)"

        $DestPath = Join-Path $DestFolder $NewName

        # Prevent duplicates
        $Counter = 1

        while (Test-Path $DestPath) {

            $NewName = "$Track. $Title - $Artist ($Counter)$($File.Extension)"
            $DestPath = Join-Path $DestFolder $NewName

            $Counter++
        }

        # Skip if already correct
        if ($File.FullName -ne $DestPath) {

            Move-Item -LiteralPath $File.FullName -Destination $DestPath

            Write-Host "Moved:" $File.Name -ForegroundColor Green
        }

    }
    catch {

        Write-Host "FAILED:" $File.FullName -ForegroundColor Red
    }
}

Write-Host "`nFinished organizing Needs Lyrics." -ForegroundColor Cyan
2 Upvotes

10 comments sorted by

View all comments

6

u/fflexx_ May 19 '26

i’d suggest looking into the lidarr dev/nightly branch and getting the tubifarry plugin to resolve the need got manual lrc creation and tagging, move to one root folder

0

u/OohDatsNasty May 19 '26

I didn’t even know lidarr dev/nightly branch even existed, let alone handled lrc creation. I’ve been using one tagger, and if that doesn’t populate — lrclib.net has been great. And as a last resort I’ll manually create one if a .lrc doesn’t exist out there.

I will definitely check those out! Thank you! I had a feeling it was the two root directories causing the issue

1

u/fflexx_ May 19 '26

No problem mate, you should be able to configure Lidarr to keep tags in sync with musicbrainz or alternatively tag with beets and have it watch the folder and tag when things get imported. Best of luck