A for /F command with a set to process the output of a command line results in starting in background one more Windows command processor with %SystemRoot%\System32\cmd.exe /c and the command line appended as additional arguments. Therefore delayed variable expansion is not enabled for this command process running in background as it would be necessary for echo !mkvmergeinfo!. It would be necessary to run the background cmd.exe with option /V:ON left to option /c and the command line to execute. But that is not possible, except running two additional cmd.exe, the first one with /c and a command line which starts with %ComSpec% /D /V:ON /C ... a second cmd.exe as suggested by aschipfl in his comment above.
I suggest to run mkvmerge.exe -i once for each *.mkv file and process the output using just internal commands of cmd.exe like FOR and IF without using find.exe and findstr.exe at all.
Example:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for %%G in (*.mkv) do (
echo(
echo Processing file "%%G" ...
for /F "delims=" %%H in ('mkvmerge.exe -i "%%G"') do (
echo(
echo Processing info line: %%H
for /F "tokens=1,3,4* delims=:( " %%I in ("%%H") do (
if "%%I" == "Track" (
for /F "delims=)" %%M in ("%%L") do (
if "%%K" == "video" (
echo ... Track %%J is a video track with video codec %%M
) else if "%%K" == "audio" (
echo ... Track %%J is an audio track with audio codec %%M
) else if "%%K" == "subtitles" (
echo ... Track %%J is a subtitles track with subtitles codec %%M
)
)
) else if "%%I" == "Attachment" (
echo ... Attachment %%J is %%K %%L
)
)
)
)
endlocal
How each line output by mkvmerge.exe -i "%%G" is processed further is up to you. This is just a demonstration which results in following output for the posted information of file test.mkv.
Processing file "test.mkv" ...
Processing info line: File 'test.mkv': container: Matroska
Processing info line: Track ID 0: video (AVC/H.264/MPEG-4p10)
... Track 0 is a video track with video codec AVC/H.264/MPEG-4p10
Processing info line: Track ID 1: audio (Opus)
... Track 1 is an audio track with audio codec Opus
Processing info line: Track ID 2: subtitles (SubRip/SRT)
... Track 2 is a subtitles track with subtitles codec SubRip/SRT
Processing info line: Attachment ID 1: type 'image/jpeg', size 30184 bytes, file name 'test.jpg'
... Attachment 1 is type 'image/jpeg', size 30184 bytes, file name 'test.jpg'
Processing info line: Attachment ID 2: type 'image/jpeg', size 30184 bytes, file name 'test2.jpg'
... Attachment 2 is type 'image/jpeg', size 30184 bytes, file name 'test2.jpg'
Processing info line: Attachment ID 3: type 'image/jpeg', size 30184 bytes, file name 'test3.jpg'
... Attachment 3 is type 'image/jpeg', size 30184 bytes, file name 'test3.jpg'
Processing info line: Chapters: 9 entries
So the first and the last line of information output are not really processed while there is a further processing on the lines with first substring (token) being case-sensitive Track or Attachment.
The second FOR command line results in starting in background with Windows installed into C:\Windows one more Windows command processor with the following command line on current file being test.mkv:
C:\Windows\System32\cmd.exe /c mkvmerge.exe -i "test.mkv"
The Windows command processor has to search first for the file mkvmerge.exe by using the environment variables PATHEXT and PATH. So if the batch file has to process 100 .mkv files, there must be executed most likely several thousand of file system accesses in total to find this executable again and again. The usage of the fully qualified file name, i.e. mkvmerge.exe with its full path, would help to reduce the number of file system accesses to exactly 100 for 100 .mkv files for 100 executions of mkvmerge.exe.
Once mkvmerge.exe is found, the second cmd.exe started in background calls this executable with its full path and passes the two arguments to it. mkvmerge.exe outputs the data to handle STDOUT of the background command process.
The output to handle STDOUT of the background command process is captured by cmd.exe processing the batch file and FOR processes the lines one after the other after started cmd.exe closed itself after mkvmerge.exe finished.
FOR with option /F ignores always empty lines. That is no problem here.
Non-empty lines would be split up by default into substrings (tokens) using normal space and horizontal tab as string delimiters, then the first substring would be checked on beginning with a semicolon which is the default end of line character in which case the line would be ignored also for further processing and finally the first space/tab delimited substring is assigned to the specified loop variable H. But that default line processing behavior is not wanted in this case. For that reason delims= is used to defined an empty list of delimiters which results in getting the entire captured line assigned to the loop variable H, except the line would start with ; which can be excluded here because of mkvmerge.exe does not output a line with a semicolon at the beginning.
The entire line is output by the demonstration code to the console window so that it can be seen how the line looks like which is processed further.
The second for /F loop makes now the real job of processing the data of the line. The line assigned to loop variable H is specified in double quotes inside the round brackets resulting in FOR interpreting the line as string to process like a line captured from a command process executed in background or a line read from a text file.
This time the string delimiters are defined with a colon, an opening round bracket and a normal space using delims=:( . There is additionally specified with tokens=1,3,4* that of interest is not only the first substring, but the first, the third, the fourth and the rest of the line not further split up into substrings using the delimiters.
For example, let us look on what happens now with the following line:
Track ID 0: video (AVC/H.264/MPEG-4p10)
This line is split up to:
Track being assigned to the specified loop variable I.
ID which is not further processed at all.
0 which is assigned to next but one loop variable J according to the ASCII table.
This is the reason for loop variables being case-sensitive.
video which is assigned to loop variable K according to the ASCII table.
AVC/H.264/MPEG-4p10) which is the rest of the line being assigned to the loop variable L.
The strings assigned to the loop variables I to L are processed further with the IF conditions whereby the round bracket at end of the codec string of a line beginning with Track is removed using one more for /F command with delims=).
It would be also possible to directly split up the captured lines into substrings as demonstrated with the following code which additionally ignores all lines beginning with Attachment on having before processed lines beginning with Track.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for %%G in (*.mkv) do (
set "Tracks="
echo(
echo Processing file "%%G" ...
for /F "tokens=1,3,4* delims=:( " %%H in ('mkvmerge.exe -i "%%G"') do (
if "%%H" == "Track" (
set "Tracks=1"
for /F "delims=)" %%L in ("%%K") do (
if "%%J" == "video" (
echo ... Track %%I is a video track with video codec %%L
) else if "%%J" == "audio" (
echo ... Track %%I is an audio track with audio codec %%L
) else if "%%J" == "subtitles" (
echo ... Track %%I is a subtitles track with subtitles codec %%L
)
)
) else if not defined Tracks (
if "%%H" == "Attachment" echo ... Attachment %%I is %%J %%K
)
)
)
endlocal
The output of this demonstration code for file test.mkv is:
Processing file "test.mkv" ...
... Track 0 is a video track with video codec AVC/H.264/MPEG-4p10
... Track 1 is an audio track with audio codec Opus
... Track 2 is a subtitles track with subtitles codec SubRip/SRT
There is undefined first with set "Tracks=" the environment variable Tracks for each file before processing the lines output by mkvmerge.exe. If there is a line beginning with Track, the environment variable Tracks is defined with value 1 whereby the value does not matter.
On all other lines there is checked first if the environment variable Tracks is still not defined. If this condition is not true because of at least one line beginning with Track was processed before, the line is completely ignored. Otherwise there were no track information processed before and for that reason lines beginning with Attachment are processed next with printing information about the attachment. The first line with File and the last line with Chapters are still completely ignored in any case.
To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.
echo /?
endlocal /?
for /?
if /?
setlocal /?
See also my answer on Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files to get knowledge why it makes sense to enclose both strings to compare in " while it does not make sense to enclose them in [ and ] because of the square brackets have no special meaning for the Windows command processor.