代码之家  ›  专栏  ›  技术社区  ›  John Meagher

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

  •  111
  • John Meagher  · 技术社区  · 16 年前

    我希望在Windows批处理脚本中获得作为变量的命令结果(请参见 how to get the result of a command in bash 对于bash脚本等价物)。最好使用可在.bat文件中使用的解决方案,但也欢迎使用其他常见的Windows脚本解决方案。

    12 回复  |  直到 5 年前
        1
  •  28
  •   PabloG    16 年前

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

    @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中。.

    @约翰:这个有什么实际用途吗?我认为您应该关注PowerShell或任何其他能够轻松执行脚本任务的编程语言(python、perl、php、ruby)

        2
  •  75
  •   Dave Jarvis aSterX    7 年前

    谦卑的 对于 多年来,司令部积累了一些有趣的能力:

    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"
    
        3
  •  23
  •   Evil Activity    16 年前

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

    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,或者为这些东西创建一个应用程序。这将极大地扩展批处理文件的可能性。

        4
  •  7
  •   Ilya Kochetov    16 年前

    你需要使用 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 “。但它只会 获取输出的第一行,而不是 全部输出

        5
  •  5
  •   PabloG    16 年前

    在“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
    
        6
  •  3
  •   Félix Saparelli    10 年前

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

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

    你可以使用 %%I 作为您想要的值。就像这样: %%i .

    并且提前 %%i 没有任何空格或CR字符,可以用于比较!!

        7
  •  2
  •   Community uzul    7 年前

    如果您正在寻找中提供的解决方案 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相同。
    • 参数上的字符串提取将返回文件名/文件夹。
    • 获取此文件夹的内容并附加到文件名.txt

    [学分] :多亏了所有其他的答案和一些挖掘 Windows XP commands 页。

        8
  •  2
  •   Tim Cooper    12 年前
    @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%"
    
        9
  •  1
  •   Adam Mitz    16 年前

    您可以在一个变量中捕获所有输出,但行之间将由您选择的字符分隔(在下面的示例中),而不是实际的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
  •  1
  •   Gilles Maisonneuve    6 年前

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

    如果您的命令位于路径中,或者该命令是一个没有空格或特殊字符的命令路径,那么所有这些语法都可以很好地工作。

    但是,如果您尝试使用位于路径包含特殊字符的文件夹中的可执行命令,则需要将命令路径括在双引号(“)中,然后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 )

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

    吉尔斯

        11
  •  0
  •   ivan rc    5 年前
    @echo off
    setlocal EnableDelayedExpansion
    FOR /F "tokens=1 delims= " %%i IN ('echo hola') DO (
        set TXT=%%i
    )
    echo 'TXT: %TXT%'
    

    结果是'txt:hola'

        12
  •  -1
  •   Jack B Nimble    16 年前

    请参考这个 http://technet.microsoft.com/en-us/library/bb490982.aspx 这就解释了如何使用命令输出。