Page 1 of 1

Ampersand and exclamation mark in concatenated variable

Posted: 2022-Dec-31, 8:30 pm
by ss64bit
Hi, I'm trying to create a batch file where I loop through a directory of audio files to create a variable holding all filenames wrapped in double quotes. I then pass this variable to foobar2000 to do some tagging.

For example, I'll have a variable that will end up like this:

Code: Select all

"01. Track 1.mp3" "02. Track 2.mp3" "03. Track 3.mp3"
I'm very close to achieving what I want, but I'm having a tiny issue with ampersands in the folder or filename. I've already read about escaping the variable, but wrapping the filename in double quotes is causing a bit of an issue.

Here's what I have so far:

Code: Select all

:: Loop through all files in folder for .mp3 files only
:: %1 is the directory filepath.
:: Then, concat all mp3s into a single line, delimited by double-quotes
set audio=%1\*.mp3
set tracks=
for /F "delims=" %%i in ('dir /s/b %audio%') do (
	call set "tracks=%%tracks%% "%%i""
)

:: Tag with foobar2000!
c:\apps\foobar2000\foobar2000.exe /tag:GUESS:"%%TRACKNUMBER%%. %%TITLE%%":%%_FILENAME%% %tracks%
I know the issue is with the call set "tracks=%%tracks%% "%%i"" line, but I'm not sure how to fix it.

Any help will be greatly appreciated. Thanks and Happy New Year!

Re: Ampersand in concatenated variable

Posted: 2023-Jan-02, 9:31 pm
by ss64bit
I've updated the code to work with ampersands, but now filenames with exclamation marks will be wrong as exclamation marks are stripped from the string. It appears that I cannot get ampersands and exclamation marks working together at the same time due to how I'm using EnableDelayedExpansion and double quotes.

Here's the revised code:

Code: Select all

setlocal EnableDelayedExpansion
set tracks=
for /r %%i in (*.mp3) do (
    set tracks=!tracks! "%%i"
)

:: Tag with foobar2000!
c:\apps\foobar2000\foobar2000.exe /tag:GUESS:"%%TRACKNUMBER%%. %%TITLE%%":%%_FILENAME%% %tracks%

endlocal
Thanks for any help.

Re: Ampersand and exclamation mark in concatenated variable

Posted: 2023-Mar-22, 7:39 am
by Rekrul
I was browsing the forum and saw your message. This should do what you want with any legal filename;

Code: Select all

@echo off
set tracks=
for /r %%i in (*.mp3) do (
set name="%%i"
call :AddTrack
)

c:\apps\foobar2000\foobar2000.exe /tag:GUESS:"%%TRACKNUMBER%%. %%TITLE%%":%%_FILENAME%% %tracks%
goto:eof

:AddTrack
set tracks=%tracks% %name%
exit /b
By putting the Set statement outside the For loop and then Calling it, you avoid the problem of variable names not being read within the loop.

I see one potential problem though: If there are a lot of files with long names and path names, the combined %tracks% variable could end up being too long for the command line. Personally, i would process each file individually;

Code: Select all

@echo off
for /r %%i in (*.mp3) do (
set name="%%i"
call :AddTags
)
goto:eof

:AddTags
c:\apps\foobar2000\foobar2000.exe /tag:GUESS:"%%TRACKNUMBER%%. %%TITLE%%":%%_FILENAME%% %name%
exit /b
The downside is that foobar2000.exe is called for each file, potentially slowing it down, depending on how long that program takes to execute. If that's an issue, it would be possible to add a counter and have it add 10-15 tracks at a time, process those, add another 10-15, do those, etc.