First, please read my answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line? It makes a big difference if first double quote is left to variable name or right to equal sign on definition of an environment variable. See also How to set environment variables with spaces?
Let us look on this code:
@echo off
set "Executable=path\to\exe"
set "TargetFile=path\to\file\to\be\read\by\exe"
for /F delims^=^ eol^= %%I in ('"%Executable%" -arg1 "%TargetFile%" 2^>^&1') do set "Data=%%I" & goto HaveData
echo No data captured!
pause
goto :EOF
:HaveData
echo Data: %Data%
pause
FOR with option /F
with string in round brackets enclosed in straight single quotes results in starting in background cmd.exe /c
with using %ComSpec% /c
with the string in round brackets as additional arguments. So one more command process is started by FOR in background to execute the specified command line between '
...'
inside the parentheses.
The full qualified file name was first assigned to an environment variable without the double quotes needed on this string containing a space or one of these characters &()[]{}^=;!'+,`~
. So the reference of the environment variable Executable
must be now enclosed in double quotes. The same needs to be done for TargetFile
.
FOR captures everything written to handle STDOUT of the started command process for being finally processed line by line after started cmd.exe
terminated itself. The output to handle STDERR is also captured by FOR, but is just redirected to STDERR of the command process executing the batch file and therefore would be just displayed in console window.
But the executable perhaps outputs the information of interest to handle STDERR instead of STDOUT. For that reason 2>&1
is used as documented by Microsoft in article about using command redirection operators to get output of executable written to STDERR redirected to STDOUT of background command process.
The redirection operators >
and &
must be escaped with caret character ^
on FOR command line to be interpreted as literal characters when Windows command interpreter processes this command line before executing command FOR which executes the embedded command line with using a separate command process started in background.
FOR processes the captured output line by line with skipping all empty lines after started executable finished and so started cmd.exe
finished, too.
By default lines starting with ;
are also ignored by FOR as the semicolon is the default end of line character. eol=
is specified to define no end of line character to avoid ignoring any non-empty line.
FOR splits up by default a line into substrings (tokens) using normal space and horizontal tab character as string delimiters. This string splitting behavior is most likely not wanted here. For that reason delims=
is specified for an empty list of delimiters to disable line splitting behavior and get assigned to specified loop variable I
the entire non-empty line currently processed by FOR.
The options list after for /F
is usually specified with using "
one or mor options"
. This is not possible here to define an empty list of delimiters and no end of line character. So the options are specified not enclosed in a double quoted string. But in this case =
and space must be escaped with ^
to be interpreted as literal characters and not as argument separators by cmd.exe
parsing this FOR command line to pass delims= eol=
as one argument string to command FOR.
So if the executable defined with environment variable Executable
outputs just one non-empty line in ANSI, this line is assigned to environment variable Data
.
But perhaps the executable outputs the information of interest not in ASCII/ANSI, but in Unicode with UTF-16 Little Endian encoding and additionally outputs two or more empty lines as for example wmic.exe
does. In this case a bug of FOR on interpreting the Unicode encoded output must be taken into account which results in deletion of environment variable Data
after being defined with the data of interest on FOR processing wrong the UTF-16 LE encoded empty lines at end of captured Unicode output. For details about this bug of FOR see How to correct variable overwriting misbehavior when parsing output? The solution used here is to leave the loop after first non-empty line is assigned to environment variable Data
by a jump to code below the label HaveData
.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
echo /?
for /?
goto /?
pause /?
set /?