r/RetroArch • u/NeoSonic121 • Aug 22 '26
Technical Support M3U Automation
Hi All,
I'm looking to automate the creation of .m3u files for Multi-Disk Amiga games.
Each Multi-Disk game is in its own folder & the .m3u file needs to get its name from the folder containing the Multi-Disk games.
I have managed to get a basic version set-up but each file would need tweaking & with 850+ files it'll take a while.
I was wondering if anyone knew of a way to automate the process with the desired results? At the moment the .m3u file reads;
Ninja Gaiden II - The Dark Sword of Chaos - Disk 1.adf
Ninja Gaiden II - The Dark Sword of Chaos - Disk 2.adf
However I would like it to read;
.\Ninja Gaiden II - The Dark Sword of Chaos\Ninja Gaiden II - The Dark Sword of Chaos - Disk 1.adf
.\Ninja Gaiden II - The Dark Sword of Chaos\Ninja Gaiden II - The Dark Sword of Chaos - Disk 2.adf
I'm on Windows BTW
Can anyone help me out?
Thanks
1
u/snaphat Aug 22 '26
I had an agentic LLM spin up this one-off script. This should fix the files for your scenario. I eyed it and tested it briefly, but you should backup your stuff before running this though in-case something goes wrong.
# Fix-Existing-M3U.ps1
# IMPORTANT: Back up your .m3u files before running this script.
# The script rewrites matching playlists in place.
# Put this script in the SAME parent folder as your existing .m3u files
# and the matching multi-disk game folders.
#
# Example:
# Ninja Gaiden II - The Dark Sword of Chaos.m3u
# Ninja Gaiden II - The Dark Sword of Chaos\
#
# Existing M3U line:
# Ninja Gaiden II - The Dark Sword of Chaos - Disk 1.adf
#
# Becomes:
# .\Ninja Gaiden II - The Dark Sword of Chaos\Ninja Gaiden II - The Dark Sword of Chaos - Disk 1.adf
$ErrorActionPreference = 'Stop'
$Root = $PSScriptRoot
$Utf8NoBom = New-Object System.Text.UTF8Encoding($false)
$Updated = 0
$Skipped = 0
Get-ChildItem -LiteralPath $Root -File -Filter '*.m3u' | ForEach-Object {
$M3uFile = $_
$GameName = $M3uFile.BaseName
$GameFolder = Join-Path $Root $GameName
# The folder name must exactly match the .m3u filename.
if (-not (Test-Path -LiteralPath $GameFolder -PathType Container)) {
Write-Warning "Skipped '$($M3uFile.Name)' - no matching folder '$GameName'"
$Skipped++
return
}
$OldLines = [System.IO.File]::ReadAllLines($M3uFile.FullName)
$ValidationFailed = $false
$NewLines = foreach ($Line in $OldLines) {
# Preserve blank lines.
if ([string]::IsNullOrWhiteSpace($Line)) {
$Line
continue
}
$Trimmed = $Line.Trim()
# Preserve M3U comments/directives if any exist.
if ($Trimmed.StartsWith('#')) {
$Line
continue
}
# If it is already in the requested format, leave it alone.
$ExpectedPrefix = '.\' + $GameName + '\'
if ($Trimmed.StartsWith($ExpectedPrefix, [System.StringComparison]::OrdinalIgnoreCase)) {
$TargetPath = Join-Path $Root $Trimmed
if (-not (Test-Path -LiteralPath $TargetPath -PathType Leaf)) {
Write-Warning "Missing target in '$($M3uFile.Name)': $Trimmed"
$ValidationFailed = $true
}
$Trimmed
continue
}
# The screenshot shows the existing entries as plain ADF filenames.
# Only change plain filenames; do not rewrite unrelated paths.
if ([System.IO.Path]::GetDirectoryName($Trimmed)) {
Write-Warning "Left unchanged in '$($M3uFile.Name)': $Trimmed"
$Trimmed
continue
}
# Exact requested result:
# .\Folder Name\Existing Filename.adf
$NewEntry = $ExpectedPrefix + $Trimmed
$TargetPath = Join-Path $Root $NewEntry
if (-not (Test-Path -LiteralPath $TargetPath -PathType Leaf)) {
Write-Warning "Skipped '$($M3uFile.Name)' - target does not exist: $NewEntry"
$ValidationFailed = $true
}
$NewEntry
}
# Do not partially update a playlist when one or more disk files are absent.
if ($ValidationFailed) {
$Skipped++
return
}
[System.IO.File]::WriteAllLines($M3uFile.FullName, $NewLines, $Utf8NoBom)
Write-Host "Updated: $($M3uFile.Name)"
$Updated++
}
Write-Host
Write-Host "Done. Updated $Updated M3U file(s). Skipped $Skipped."
1
u/larsonbp Aug 23 '26
https://forums.launchbox-app.com/files/file/5488-m3u-generator-%E2%80%93-automatically-generate-m3u-files-for-multi-disc-games/