使用 Windows 批处理文件中命令的结果设置变量的值

巴斯环境中工作时,为了将变量的值设置为命令的结果,我通常会这样做:

var=$(command -args)

其中 var是由命令 command -args设置的变量。

实现这一点的一种更为传统的方法是:

set var=`command -args`

也就是说,我如何在 Windows 批处理文件中用命令的结果来设置变量的值?我试过了:

set var=command -args

但是我发现 var被设置为 command -args而不是命令的输出。

179601 次浏览

The only way I've seen it done is if you do this:

for /f "delims=" %a in ('ver') do @set foobar=%a

ver is the version command for Windows and on my system it produces:

Microsoft Windows [Version 6.0.6001]

Source

To do what Jesse describes, from a Windows batch file you will need to write:

for /f "delims=" %%a in ('ver') do @set foobar=%%a

But, I instead suggest using Cygwin on your Windows system if you are used to Unix-type scripting.

Here's how I do it when I need a database query's results in my batch file:

sqlplus -S schema/schema@db @query.sql> __query.tmp
set /p result=<__query.tmp
del __query.tmp

The key is in line 2: "set /p" sets the value of "result" to the value of the first line (only) in "__query.tmp" via the "<" redirection operator.

One needs to be somewhat careful, since the Windows batch command:

for /f "delims=" %%a in ('command') do @set theValue=%%a

does not have the same semantics as the Unix shell statement:

theValue=`command`

Consider the case where the command fails, causing an error.

In the Unix shell version, the assignment to "theValue" still occurs, any previous value being replaced with an empty value.

In the Windows batch version, it's the "for" command which handles the error, and the "do" clause is never reached -- so any previous value of "theValue" will be retained.

To get more Unix-like semantics in Windows batch script, you must ensure that assignment takes place:

set theValue=
for /f "delims=" %%a in ('command') do @set theValue=%%a

Failing to clear the variable's value when converting a Unix script to Windows batch can be a cause of subtle errors.

Set "dateTime="
For /F %%A In ('powershell get-date -format "{yyyyMMdd_HHmm}"') Do Set "dateTime=%%A"
echo %dateTime%
pause

enter image description here Official Microsoft docs for for command

Here are two approaches:

@echo off


:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;;set "[[=>"#" 2>&1&set/p "&set "]]==<# & del /q # >nul 2>&1" &::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


:: --examples


::assigning chcp command output to %code-page% variable
chcp %[[%code-page%]]%
echo 1: %code-page%


::assigning whoami command output to %its-me% variable
whoami %[[%its-me%]]%
echo 2: %its-me%




::::::::::::::::::::::::::::::::::::::::::::::::::
;;set "\{\{=for /f "tokens=* delims=" %%# in ('" &::
;;set "--=') do @set ""                        &::
;;set "}}==%%#""                               &::
::::::::::::::::::::::::::::::::::::::::::::::::::


:: --examples


::assigning ver output to %win-ver% variable
%\{\{% ver %--%win-ver%}}%
echo 3: %win-ver%




::assigning hostname output to %my-host% variable
%\{\{% hostname %--%my-host%}}%
echo 4: %my-host%

the output of the script:

1: Active code page: 65001
2: mypc\user
3: Microsoft Windows [Version 10.0.19042.1110]
4: mypc

Explanation:

1] the parts ending with &:: are end-of-line comment and can be ignored. I've put them only for macro enclosing

2] ;; at the start of the line will be ignored as ; is a standard delimiter for batch script. It is put there as it reminds a comment and to further enhance where the macro definitions are assigned.

3] the technique used is called 'macro' it assigns command to a variable and when the variable is invoked the command is executed.

4] the first macro defined contains two parts:

set "[[=>"#" 2>&1&set/p "

and

set "]]==<# & del /q # >nul 2>&1"

separated by & which allows me to define them on one line. The first takes the output of a command and redirects it ot a file #. And adds set/p in order to start the reading the file with set /p technique .The second macro finishes the set /p reading with <# and then deletes the file. The text between two macros is the name of the variable. Something like set /p myVariable=<#

5] The second macro contains three parts and expanded is just a for /f loop. Probably can be done in a more elegant way.