CMD: extract part of a file name and use it as a variable

advertisements

I ripped my CDs with EAC to CUE+WAV files, added cover art and all my files are in the same folder with filenames pattern "Album artist - Album title", for ex.:

Clannad - Legend.wav/cue/jpg
David Bowie - Best Of Bowie [Disc 1].wav/cue/jpg
David Bowie - Best Of Bowie [Disc 2].wav/cue/jpg

I'm new to this so I wrote a simple CMD batch to convert my music to FLAC format, but it requires manual copying and pasting of the actual wav/cue/jpg filenames and input of album artist, disc no. and total disc no. for their corresponding tags. It cannot be stored in cuesheet file for some reason, but in my case I have them in filenames as you can see above).

ECHO WAV/CUE/JPG FILENAME
SET /P "input="
ECHO ALBUMARTIST
SET /P "albumartist="
ECHO DISCNUMBER
SET /P "discnumber="
ECHO TOTALDISCS
SET /P "totaldiscs="

flac.exe -0 --picture="D:\Music\%input%.jpg" --tag-from-file="CUESHEET=D:\Music\%input%.cue" -T "ALBUMARTIST=%albumartist%" -T "DISCNUMBER=%discnumber%" -T "TOTALDISCS=%totaldiscs%" "D:\Music\%input%.wav"

My question is about automation of converting all my ripped albums. How can I extract album artist/disc no./total disc no. info from filenames and loop that for every .wav file?


This is very similar to Magoo's answer, with some bug fixes, and everything is done in one master loop without a CALL. As with Magoo's answer, modify your destination folder at the beginning to suit your needs.

@echo off
:: Delayed expansion must be disabled to protect ! when expanding FOR variables.
:: It is normally disabled by default, but I'm making it explicit, just to be sure.
setlocal disableDelayedExpansion

:: Define where source files are coming from
set "source=D:\Music"

:: Define where output should be stored
set "destination=D:\Music"

pushd "%destination%"

:: Iterate each .wav file (A) and only proceed if .jpg and .cue also exists
for /f "delims=" %%A in ('dir /b /a-d "%source%\*.wav"') do if exist "%source%\%%~nA.jpg" if exist "%source%\%%~nA.cue" (

  %= Get base name with path, but without extension =%
  set "file=%source%\%%~nA"

  %= Extract "artist - album " (B) and "Disc #" (C) from base name (~nA) =%
  for /f "delims=[] tokens=1,2" %%B in ("%%~nA") do (

    %= Extract "artst " (D) from "artist - abum ". (~nxD) trims trailing space =%
    for /f "delims=-" %%D in ("%%B") do set "artist=%%~nxD"

    %= Extract the number (E) from "Disc #", use 1 as default if not there =%
    set "disc=1"
    for /f "tokens=2" %%E in ("%%C") do set "disc=%%E"

    %= Count the number of discs (F), will be 0 if no [Disc #] =%
    %= The [ is appended to name to prevent something like "Greatest Hits 2" from matching "Greatist Hits" =%
    for /f %%F in ('dir /b /a-d "%source%\%%B[*.wav" 2^>nul ^|find /c /v ""') do set "count=%%F"

    %= temporarily enable delayed expansion to access variables set within loop =%
    setlocal enableDelayedExpansion

    %= Set count to 1 if no [Disc #] =%
    if !count! equ 0 set /a count=1

    flac.exe -0 --picture="!file!.jpg" --tag-from-file="CUESHEET=!file!.cue" -T "ALBUMARTIST=!artist!" -T "DISCNUMBER=!disc!" -T "TOTALDISCS=!count!" "!file!.wav"

    %= pop the setlocal stack to get back to state at beginning of loop =%
    endlocal
  )
)
popd

You may want to add a check to only proceed if the FLAC file does not already exist so you can run the script multiple times without reprocessing files. The outer loop would look something like this, but I can't be sure since I don't know the format of the output file name:

for /f "delims=" %%A in ('dir /b /a-d "%source%\*.wav"') do if exist "%source%\%%~nA.jpg" if exist "%source%\%%~nA.cue" if not exist "%destination%\%%~nA.flac" (


The logic is much simpler using my JREPL.BAT utility if you understand regular expressions:

@echo off
:: Delayed expansion must be disabled to protect ! when expanding FOR variables.
:: It is normally disabled by default, but I'm making it explicit, just to be sure.
setlocal disableDelayedExpansion

:: Define where source files are coming from
set "source=D:\music"

:: Define where output should be stored
set "destination=D:\music"

pushd "%destination%"

:: Iterate all *.wav and use JREPL to format result as "fullFileName|artist - album|artist|Disc#"
::                                                      %%A          %%B            %%C    %%D
:: Only proceed if .jpg and .cue also exist
for /f "tokens=1-4 delims=|" %%A in (
  'dir /b /a-d "%source%\*.wav"^|jrepl "^((.+?) - .+?)(?:\[Disc (\d+)])?\.wav$" "$&|$1|$2|$3" /i'
) do if exist "%%~nA.jpg" if exist "%%~nA.cue" (

  %= disc and count are both 1 if %%D is empty =%
  if "%%D" equ "" (
    flac.exe -0 --picture="%source%\%%~nA.jpg" --tag-from-file="CUESHEET=%source%\%%~nA.cue" -T "ALBUMARTIST=%%C" -T "DISCNUMBER=1" -T "TOTALDISCS=1" "%source%\%%A"

  %= else count the number of .wav files =%
  ) else for /f %%E in ('dir /b /a-d "%%B[*.wav"^|find /c /v ""') do (
    flac.exe -0 --picture="%source%\%%~nA.jpg" --tag-from-file="CUESHEET=%source%\%%~nA.cue" -T "ALBUMARTIST=%%C" -T "DISCNUMBER=%%D" -T "TOTALDISCS=%%E" "%source%\%%A"
  )
)

popd

Again, you can add an IF to the outer loop to proceed only if the .flac file does not already exist in the destination.