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

时间:2008-09-20 15:13:29

标签: windows scripting batch-file

我希望将命令的结果作为Windows批处理脚本中的变量(请参阅how to get the result of a command in bash了解bash脚本等效项)。可以在.bat文件中使用的解决方案是首选,但也欢迎其他常见的Windows脚本解决方案。

13 个答案:

答案 0 :(得分:76)

多年来,简单的 for 命令积累了一些有趣的功能:

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

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

要捕获多行输出,它仍然可以基本上是单行(使用变量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%

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

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

答案 1 :(得分:31)

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

@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

所有输出行都存储在VAR中,以“!”分隔。

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

答案 2 :(得分:23)

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

CD > tmpFile
SET /p myvar= < tmpFile
DEL tmpFile
echo test: %myvar%

它正在使用临时文件,所以它不是最漂亮的,但它确实有效! '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

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

答案 3 :(得分:7)

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

从评论到这篇文章:

  

该链接的命令为“/P”,表示会将Set /P _MyVar=<MyFilename.txt设置为第一行   来自_MyVar。这可能是   用作“MyFilename.txt”和“myCmd > tmp.txt”。但它只会   得到输出的第一行,而不是   所有输出

答案 4 :(得分:5)

在“V”环境变量中设置最新文件

的示例
FOR /F %I IN ('DIR *.* /O:D /B') DO SET V=%I

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

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

答案 5 :(得分:3)

只需使用FOR命令的结果即可。例如(在批处理文件中):

for /F "delims=" %%I in ('dir /b /a-d /od FILESA*') do (echo %%I)

您可以使用%%I作为所需的值。就像这样:%%I

事先%%I没有任何空格或CR字符,可用于比较!!

答案 6 :(得分:2)

如果您正在寻找Using the result of a command as an argument in bash?

中提供的解决方案

然后是代码:

@echo off
if not "%1"=="" goto get_basename_pwd
for /f "delims=X" %%i in ('cd') do call %0 %%i
for /f "delims=X" %%i in ('dir /o:d /b') do echo %%i>>%filename%.txt
goto end

:get_basename_pwd
set filename=%~n1

:end
  • 这将使用CD命令的结果调用自身,与pwd相同。
  • 参数上的字符串提取将返回文件名/文件夹。
  • 获取此文件夹的内容并附加到filename.txt

[致谢] :感谢所有其他答案,并在Windows XP commands页面上进行了一些挖掘。

答案 7 :(得分:2)

@echo off

ver | find "6.1." > nul
if %ERRORLEVEL% == 0 (
echo Win7
for /f "delims=" %%a in ('DIR "C:\Program Files\Microsoft Office\*Outlook.EXE" /B /P /S') do call set findoutlook=%%a
%findoutlook%
)

ver | find "5.1." > nul
if %ERRORLEVEL% == 0 (
echo WinXP
for /f "delims=" %%a in ('DIR "C:\Program Files\Microsoft Office\*Outlook.EXE" /B /P /S') do call set findoutlook=%%a
%findoutlook%
)
echo Outlook dir:  %findoutlook%
"%findoutlook%"

答案 8 :(得分:2)

我想在上述解决方案中添加一句话:

如果您的命令在路径中找到,或者如果命令是没有空格或特殊字符的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.

$ 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.

`$ 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.

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

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%

结果是正确的:

My selected folder: F:\GLW7\Distrib\System\OS install, recovery, VM\
Press any key to continue . . .

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

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

如果有人能够通过复杂的路径获得更好的解决方案,我会很高兴听到它。

吉勒

答案 9 :(得分:1)

您可以捕获一个变量中的所有输出,但这些行将由您选择的字符(下例中的#)而不是实际的CR-LF分隔。

@echo off
setlocal EnableDelayedExpansion
for /f "delims=" %%i in ('dir /b') do (
    if "!DIR!"=="" (set DIR=%%i) else (set DIR=!DIR!#%%i)
)
echo directory contains:
echo %DIR%

第二个版本,如果您需要逐行打印内容。这样做的好处是“dir / b”不会有重复的输出行,因此在一般情况下它可能不起作用。

@echo off
setlocal EnableDelayedExpansion
set count=0
for /f "delims=" %%i in ('dir /b') do (
    if "!DIR!"=="" (set DIR=%%i) else (set DIR=!DIR!#%%i)
    set /a count = !count! + 1
)

echo directory contains:
echo %DIR%

for /l %%c in (1,1,%count%) do (
    for /f "delims=#" %%i in ("!DIR!") do (
        echo %%i
        set DIR=!DIR:%%i=!
    )
)

答案 10 :(得分:0)

@echo off
setlocal EnableDelayedExpansion
FOR /F "tokens=1 delims= " %%i IN ('echo hola') DO (
    set TXT=%%i
)
echo 'TXT: %TXT%'

结果是'TXT:hola'

答案 11 :(得分:0)

您应该使用for命令,这是一个示例:

@echo off
rem Commands go here
exit /b
:output
for /f "tokens=* useback" %%a in (`%~1`) do set "output=%%a"

,您可以使用call :output "Command goes here",然后输出将在%output%变量中。

注意:如果您的命令输出为多行,则此工具会将输出set {{1}}移至多行命令的最后一行。

答案 12 :(得分:-1)

请参阅此http://technet.microsoft.com/en-us/library/bb490982.aspx,其中说明了如何使用命令输出。