3

I'm looking to store the video codec as a variable in a batch file to automate some video conversion, but not wanting to convert things which are already the right codec.

This produces a the codec successfully (hevc)

C:\ffmpeg\bin\ffprobe.exe -v error -select_streams v:0 -show_entries` stream=codec_name -of default=noprint_wrappers=1:nokey=1 video.mkv
pause

However I've been unable to store that result in a variable, I've followed a number of examples which suggest this layout.

for /F "delims=" %%I in ('C:\ffmpeg\bin\ffprobe.exe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 video.mkv') do set "codec=%%I"
echo %codec%

however this results this error: "Argument 'noprint_wrappers' provided as input filename, but 'codec_name' was already specified."

I'm really not sure where to go as all my reading suggest that this is the correct way to store the variable.

RyanMe321
  • 177
  • 3
  • 11
  • 4
    within the `'` (single quotes), escape each `=` with a caret (`^`) thus : `...ult^=noprint_wrappers^=1:nokey^=1 vi...` to inform `for` that the `=` are literal. – Magoo Jun 12 '17 at 06:15

1 Answers1

6

The solution to the example question you linked already shows you what you have missed and explicitly instructs you to escape the equal-to signs like ^=, so why do you not do it?

for /F "delims=" %%I in ('C:\ffmpeg\bin\ffprobe.exe -v error -select_streams v:0 -show_entries stream^=codec_name -of default^=noprint_wrappers^=1:nokey^=1 video.mkv') do set "codec=%%I"
echo(%codec%

The problem is that the =, besides SPACE, TAB, ,, ; and the non-break space, ASCII 0xFF, constitutes a token separator to the command interpreter, so it gets lost (or replaced by a SPACE) when the command line is parsed. Escaping annulates the special meaning and preserves the character literally.

As an alternative to escaping, delayed expansion can be used, like this:

set "CommandLine=C:\ffmpeg\bin\ffprobe.exe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 video.mkv"
setlocal EnableDelayedExpansion
for /F "delims=" %%I in ('!CommandLine!') do set "codec=%%I"
echo(%codec%
endlocal

This works, because the command line string appears quoted in the assignment statement (set), so any token separators and other special characters are not recognised, and the variable CommandLine is expanded after the command line has been parsed, so special characters like token separators are not recognised at that moment any more.

Regard that the value of codec is no longer available beyond endlocal, unless you establish suitable countermeasures.

aschipfl
  • 33,626
  • 12
  • 54
  • 99
  • Are you sure about the output line in the delayed expansion variant `echo(%codec%`? Should it not be `echo(!codec!)`? – PeterCo Jun 24 '20 at 13:14
  • @PeterCo, having delayed expansion enabled does not disallow to use normal (immediate) `%`-expansion; but yes, `!codec!` would generally be better since `%codec%` could lead to problems when the expanded string contains exclamation marks `!` on its own, which would then be consumed by delayed expansion… – aschipfl Jun 24 '20 at 14:19