Home > Enterprise >  Why directing output of command to a variable doesnt work in batch file
Why directing output of command to a variable doesnt work in batch file

Time:10-04

I am trying to assign the output of the command python --version to a variable in batch script but it does not work. Here is the sample code I am using

FOR /F "tokens=* USEBACKQ" %%F IN (`python --version`) DO (
SET message=%%F
)
ECHO %message%

Although it prints the version for python, it does not assign to the variable var. If I use another command instead of python --version then the output is correctly assigned. e.g. using dir works.

What could be wrong?

NOTE -

@echo off 
set message=Hello

FOR /F "tokens=* USEBACKQ" %%F IN (`python --version`) DO (
SET message=%%F
)
ECHO %message%
PAUSE

OUTPUT -

C:\Users\nik>extra.bat
Python 2.7.9
Hello
Press any key to continue . . .

CodePudding user response:

The installed version of Python outputs obviously the version information to handle STDERR (standard error) instead of handle STDOUT (standard output). For that reason it is necessary to redirect the standard error stream with the version information to standard output stream using 2>&1 as described by Microsoft in the documentation about Using command redirection operators.

The command line to use is:

for /F "delims=" %%I in ('python.exe --version 2^>^&1') do set "message=%%I"

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.

FOR respectively cmd.exe processing the batch file with this command line starts in background one more command process with %ComSpec% /c and the command line specified within ' appended as additional arguments. Therefore is executed with Windows installed into C:\Windows in the background:

C:\Windows\System32\cmd.exe /c python.exe --version 2>&1

The command process in background searches now for an executable python.exe as described at What is the reason for "X is not recognized as an internal or external command, operable program or batch file"? When the file python.exe could be found by cmd.exe running in background without a visible console window, it executes it and Python outputs the version information to standard error stream which is redirected to standard output stream of the background command process.

The started cmd.exe closes itself after python.exe terminated itself after printing the version information.

The cmd.exe instance processing the batch file captures everything written to handle STDOUT of started background command process and FOR processes the captured lines after started cmd.exe closed itself.

There is split up by default a non-empty captured line into substrings using normal space and horizontal tab as string delimiters. If the first substring after removal of 0 or more leading spaces/tabs starts with a semicolon, the captured line is ignored, otherwise the first substring is assigned to the specified loop variable I.

The default line handling behavior is not wanted here. For that reason the for /F option delims= defines an empty list of string delimiters to disable the line splitting behavior to get the entire captured line assigned to the specified loop variable I. The implicit default eol=; (semicolon is end of line) can be kept in this case as the version information output by Python starts never with a semicolon.

  • Related