为什么将命令输出重定向到变量在批处理文件中不起作用

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

我试图将命令 python --version 的输出分配给批处理脚本中的一个变量,但它不起作用。 这是我使用的示例代码

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

虽然它打印了 python 的版本,但它没有分配给变量 var。 如果我使用另一个命令而不是 python --version 则输出被正确分配。例如使用 dir 有效。

有什么问题吗?

注意-

@echo off 
set message=Hello

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

输出-

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

安装的Python版本显然输出版本信息来处理STDERR(标准错误)而不是处理STDOUT (标准输出)。因此,有必要使用 2>&1 将带有版本信息的标准错误流重定向到标准输出流,如 Microsoft 在有关 Using command redirection operators.

的文档中所述

要使用的命令行是:

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

重定向运算符 >& 必须在 FOR 命令行上使用脱字符 ^ 进行转义,以被解释为文字字符当 Windows 命令解释器在执行命令 FOR.

之前处理此命令行时

FOR 分别 cmd.exe 使用此命令行处理批处理文件在后台启动另一个命令进程 %ComSpec% /c 并且命令行在 ' 作为附加参数附加。因此在后台将 Windows 安装到 C:\Windows 中执行:

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

后台命令进程现在搜索可执行文件 python.exe,如 所述 当文件 python.exe 可以被 cmd.exe 运行 找到时在没有可见控制台的后台 window,它执行它并且 Python 将版本信息输出到标准错误流,标准错误流被重定向到后台命令进程的标准输出流。

启动的 cmd.exe 在打印版本信息后 python.exe 自行终止后自行关闭。

处理批处理文件的 cmd.exe 实例捕获为处理已启动的后台命令进程和 FOR 进程的 STDOUT 编写的所有内容开始后捕获的行 cmd.exe 自行关闭。

默认情况下 将非空捕获行拆分为子字符串,使用普通 space 和水平制表符作为字符串分隔符。如果删除 0 个或多个前导后的第一个子字符串 spaces/tabs 以分号开头,则捕获的行将被忽略,否则将第一个子字符串分配给指定的循环变量 I.

这里不需要默认的行处理行为。出于这个原因,for /F 选项 delims= 定义了一个空的字符串定界符列表,以禁用行拆分行为,从而将整个捕获的行分配给指定的循环变量 I。在这种情况下可以保留隐式默认值 eol=;(分号是行尾),因为 Python 输出的版本信息从不以分号开头。