如何在Windows中的变量中获取命令的结果?

Joh*_*her 120 windows scripting batch-file

我希望将命令的结果作为Windows批处理脚本中的变量(请参阅如何在bash中获取bash脚本等效命令的结果).可以在.bat文件中使用的解决方案是首选,但也欢迎其他常见的Windows脚本解决方案.

tar*_*ate 78

多年来,谦逊命令积累了一些有趣的能力:

D:\> FOR /F "delims=" %i IN ('date /t') DO set today=%i
D:\> echo %today%
Sat 20/09/2008
Run Code Online (Sandbox Code Playgroud)

请注意,"delims="覆盖默认空格和制表符分隔符,以便date命令的输出一次全部吞噬.

要捕获多行输出,它仍然可以基本上是单行(使用变量lf作为结果变量中的分隔符):

REM NB:in a batch file, need to use %%i not %i
setlocal EnableDelayedExpansion
SET lf=-
FOR /F "delims=" %%i IN ('dir \ /b') DO if ("!out!"=="") (set out=%%i) else (set out=!out!%lf%%%i)
ECHO %out%
Run Code Online (Sandbox Code Playgroud)

要捕获管道表达式,请使用^|:

FOR /F "delims=" %%i IN ('svn info . ^| findstr "Root:"') DO set "URL=%%i"
Run Code Online (Sandbox Code Playgroud)

  • @Rabarberski:如果在命令行上直接输入`for`命令,则使用单个'%`.如果在批处理文件中使用它,则使用`%%`. (18认同)
  • 我发现你的答案只有当我使用双百分号时,即`FOR/F'delims ="%% i IN('date/t')DO今天设置= %% i` (11认同)

Pab*_*loG 32

如果必须捕获所有命令输出,则可以使用如下批处理:

@ECHO OFF
IF NOT "%1"=="" GOTO ADDV
SET VAR=
FOR /F %%I IN ('DIR *.TXT /B /O:D') DO CALL %0 %%I
SET VAR
GOTO END

:ADDV
SET VAR=%VAR%!%1

:END
Run Code Online (Sandbox Code Playgroud)

所有输出行都存储在VAR中,以"!"分隔.

@John:这有什么实际用途吗?我认为您应该观看PowerShell或任何其他能够轻松执行脚本任务的编程语言(Python,Perl,PHP,Ruby)

  • *这有什么实际用途吗?*你在开玩笑吧?这在其他shell(我猜所有的GNU/Linux)中一直使用,它非常有用. (22认同)
  • 有实际用途,实际上......有点儿.我想使用PowerShell脚本来查找特定的Visual Studio路径,但是我需要的那个路径是一个批处理文件,它设置了一堆env变量,所以我可以调用editbin ...所以我需要找到路径并将其返回到`cmd`的调用实例,以便我可以在那里运行它.......是的,这和声音一样糟糕.Visual Studio让我有时想哭.@ Ajedi32我认为*你*意味着**批**脚本是过去的可怕遗物.;) (3认同)
  • @PiotrDobrogost 我认为他想说的是 bash 脚本是过去可怕的遗物(您需要使用 *for 循环* 来捕获程序的输出?真的吗?)当你发现自己需要使用变量时,你应该使用更现代的东西,比如 PowerShell。 (2认同)

Evi*_*ity 23

要获取当前目录,您可以使用:

CD > tmpFile
SET /p myvar= < tmpFile
DEL tmpFile
echo test: %myvar%
Run Code Online (Sandbox Code Playgroud)

虽然它正在使用临时文件,但它并不是最漂亮的,但它确实有效!'CD'将当前目录放在'tmpFile'中,'SET'加载tmpFile的内容.

这是一个带有"数组"的多行的解决方案:

@echo off

rem ---------
rem Obtain line numbers from the file
rem ---------

rem This is the file that is being read: You can replace this with %1 for dynamic behaviour or replace it with some command like the first example i gave with the 'CD' command.
set _readfile=test.txt

for /f "usebackq tokens=2 delims=:" %%a in (`find /c /v "" %_readfile%`) do set _max=%%a
set /a _max+=1
set _i=0
set _filename=temp.dat

rem ---------
rem Make the list
rem ---------

:makeList
find /n /v "" %_readfile% >%_filename%

rem ---------
rem Read the list
rem ---------

:readList
if %_i%==%_max% goto printList

rem ---------
rem Read the lines into the array
rem ---------
for /f "usebackq delims=] tokens=2" %%a in (`findstr /r "\[%_i%]" %_filename%`) do set _data%_i%=%%a
set /a _i+=1
goto readList

:printList
del %_filename%
set _i=1
:printMore
if %_i%==%_max% goto finished
set _data%_i%
set /a _i+=1
goto printMore

:finished
Run Code Online (Sandbox Code Playgroud)

但是你可能想考虑转移到另一个更强大的shell或为这些东西创建一个应用程序.它正在扩展批处理文件的可能性.

  • 要获取当前目录,您可以使用echo%CD% (5认同)

Ily*_*tov 8

您需要使用SET带参数的命令/P并将输出定向到它.例如,请参阅http://www.ss64.com/nt/set.html.将适用于CMD,不确定.BAT文件

从评论到这篇文章:

该链接有命令" Set /P _MyVar=<MyFilename.txt",表示它将设置_MyVar为第一行MyFilename.txt.这可以用作" myCmd > tmp.txt"和" set /P myVar=<tmp.txt".但它只会获得输出的第一行,而不是所有输出

  • 该链接具有命令"Set/P _MyVar = <MyFilename.txt",表示它将_MyVar设置为MyFilename.txt的第一行.这可以用作"myCmd> tmp.txt"和"set/P myVar = <tmp.txt".但它只会获得输出的第一行,而不是所有输出. (2认同)
  • 比for命令的语法好得多 (2认同)

Pab*_*loG 5

在"V"环境变量中设置最新文件的示例

FOR /F %I IN ('DIR *.* /O:D /B') DO SET V=%I
Run Code Online (Sandbox Code Playgroud)

在批处理文件中,您必须在循环变量中使用双前缀:

FOR /F %%I IN ('DIR *.* /O:D /B') DO SET V=%%I
Run Code Online (Sandbox Code Playgroud)

  • 我以前见过这种方法,但看起来真的很笨拙.它还有一个问题,它只会捕获变量中命令的最后一行输出. (2认同)

Gil*_*uve 5

我想对上述解决方案补充一点:

如果在路径中找到您的命令或者命令是不带空格或特殊字符的 cmdpath,则所有这些语法都可以正常工作。

但是,如果您尝试使用位于路径包含特殊字符的文件夹中的可执行命令,则需要将命令路径用双引号 (") 括起来,然后 FOR /F 语法将不起作用。

例子:

$ for /f "tokens=* USEBACKQ" %f in (
    `""F:\GLW7\Distrib\System\Shells and scripting\f2ko.de\folderbrowse.exe"" Hello '"F:\GLW7\Distrib\System\Shells and scripting"'`
) do echo %f
The filename, directory name, or volume label syntax is incorrect.
Run Code Online (Sandbox Code Playgroud)

或者

$ for /f "tokens=* USEBACKQ" %f in (
      `"F:\GLW7\Distrib\System\Shells and scripting\f2ko.de\folderbrowse.exe" "Hello World" "F:\GLW7\Distrib\System\Shells and scripting"`
) do echo %f
'F:\GLW7\Distrib\System\Shells' is not recognized as an internal or external command, operable program or batch file.
Run Code Online (Sandbox Code Playgroud)

或者

`$ for /f "tokens=* USEBACKQ" %f in (
     `""F:\GLW7\Distrib\System\Shells and scripting\f2ko.de\folderbrowse.exe"" "Hello World" "F:\GLW7\Distrib\System\Shells and scripting"`
) do echo %f
'"F:\GLW7\Distrib\System\Shells and scripting\f2ko.de\folderbrowse.exe"" "Hello' is not recognized as an internal or external command, operable program or batch file.
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我发现使用命令并将其结果存储在变量中的唯一解决方案是将(临时)默认目录设置为命令本身之一:

pushd "%~d0%~p0"
FOR /F "tokens=* USEBACKQ" %%F IN (
    `FOLDERBROWSE "Hello world!" "F:\GLW7\Distrib\System\Layouts (print,display...)"`
) DO (SET MyFolder=%%F)
popd
echo My selected folder: %MyFolder%
Run Code Online (Sandbox Code Playgroud)

那么结果是正确的:

My selected folder: F:\GLW7\Distrib\System\OS install, recovery, VM\
Press any key to continue . . .
Run Code Online (Sandbox Code Playgroud)

当然,在上面的示例中,我假设我的批处理脚本与可执行命令之一位于同一文件夹中,以便我可以使用“%~d0%~p0”语法。如果这不是您的情况,那么您必须找到一种方法来定位命令路径并将默认目录更改为其路径。

注意:对于那些想知道的人,这里使用的示例命令(选择文件夹)是 FOLDERBROWSE.EXE。我在网站 f2ko.de ( http://f2ko.de/en/cmd.php ) 上找到了它。

如果有人对通过复杂路径访问的此类命令有更好的解决方案,我将非常高兴听到它。

吉尔斯