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

时间:2020-03-06 14:29:11  来源:igfitidea点击:

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

解决方案

请参考此http://technet.microsoft.com/zh-cn/library/bb490982.aspx,其中介绍了如何使用命令输出。

我们需要将SET命令与参数/ P一起使用,并将输出定向到它。
例如,请参见http://www.ss64.com/nt/set.html。适用于CMD,不确定.BAT文件

从对此帖子的评论:

That link has the command "Set /P
  _MyVar=<MyFilename.txt" which says it will set _MyVar to the first line
  from MyFilename.txt. This could be
  used as "myCmd > tmp.txt" with "set
  /P myVar=<tmp.txt". But it will only
  get the first line of the output, not
  all the output

在" 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

这些年来,谦虚的指挥积累了一些有趣的功能:

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

请注意,"" 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%

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

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

要获取当前目录,可以使用以下命令:

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或者为此应用程序创建一个应用程序。它极大地扩展了批处理文件的可能性。

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

@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)

我们可以将所有输出捕获到一个变量中,但是这些行将由我们选择的字符(在下面的示例中)代替实际的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=!
    )
)

如果我们正在寻找使用命令结果作为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
  • 这将使用与pwd相同的CD命令的结果来调用自身。
  • 参数上的字符串提取将返回文件名/文件夹。
  • 获取此文件夹的内容并追加到filename.txt

[学分]:感谢所有其他答案,以及Windows XP命令页面上的一些内容。