MS 배치 파일을 사용하여 프로그램 출력을 변수에 할당


290

MS 배치 파일을 사용하여 프로그램 출력을 변수에 할당해야합니다.

GNU Bash 셸에서 사용할 것 VAR=$(application arg0 arg1)입니다. 배치 파일을 사용하는 Windows에서도 비슷한 동작이 필요합니다.

같은 것 set VAR=application arg0 arg1.

답변:


433

한 가지 방법은 다음과 같습니다.

application arg0 arg1 > temp.txt
set /p VAR=<temp.txt

다른 것은 :

for /f %%i in ('application arg0 arg1') do set VAR=%%i

첫 번째주의 %에서이 %%i을 탈출하는 데 사용됩니다 %뒤에 배치 파일에서가 아닌 명령 줄에서 위의 코드를 사용할 때 필요하다. 당신 test.bat이 다음과 같은 것을 상상해보십시오 .

for /f %%i in ('c:\cygwin64\bin\date.exe +"%%Y%%m%%d%%H%%M%%S"') do set datetime=%%i
echo %datetime%

11
이것은 훌륭한 트릭입니다. 왜 파이프와 함께 작동하지 않는지 궁금합니다
Bill K

25
이것은 한 줄의 텍스트 인 출력에만 적용됩니다 (첫 번째 줄 바꿈 후 생략 된 줄).
GroovyCakes

20
@Machta 파이프는 앞에 괄호 안의 표현 안에서 ^ 기호로 이스케이프해야합니다. 예 :for /f "tokens=3" %%i in ('route print ^| findstr "\<0.0.0.0\>"') do set "myVar=%%i"
Emanuele Del Grande

8
공백이있는 줄에는 작동하지 않습니다. 예를 들어 : ( 'ver')의 / f %% i에 대해 VAR = %% i를 설정하십시오. @Renat이 쓴 것처럼 "tokens = *"를 추가해야합니다
Yura Shinkarev

2
@GroovyCakes 출력의 여러 줄에 대한 질문은 중복 된 질문에 대한 이 답변 으로 답변 됩니다
icc97

67

이 이전 답변 외에도 파이프는 캐럿 기호로 이스케이프 된 for 문 내부에서 사용할 수 있습니다.

    for /f "tokens=*" %%i in ('tasklist ^| grep "explorer"') do set VAR=%%i

1
두 가지 중요한 점 : 토큰을 사용하여 파이프를 빠져 나가도록합니다.
Christopher Oezbek

6
CLI에서 작동하며 더 쉽게 땜질하기 위해 복사하여 붙여 넣을 수있는 동등한 버전입니다. for /f "tokens=*" %i in ('tasklist ^| findstr explorer') do @echo %i그러나 일반적으로 usebackq복잡한 명령을 처리하는 데 사용해야합니다.
Amit Naidu

출력에서 공백을 처리하기 위해 토큰이 필요했습니다.
Mark Ingram

따옴표는 다음과 같이 작동 for /f "tokens=*" %%i in ('"tasklist | grep explorer"') do set VAR=%%i합니다. 명령 자체에 따옴표가 없으면 더 쉬워집니다.

10

@OP, for 루프 를 사용 하여 숫자 이외의 것을 출력하는 경우 프로그램의 리턴 상태를 캡처 할 수 있습니다.


8

응용 프로그램의 출력이 숫자 리턴 코드라고 가정하면 다음을 수행 할 수 있습니다.

application arg0 arg1
set VAR=%errorlevel%

5
불행히도 출력은 문자열입니다.
initialZero

확인. 나는 이것을 후손을 위해 유지하지만 @jdigital의 링크를 살펴보면 출력을 임시 파일로 파이핑하는 방법에 대해 이야기합니다.
akf

1
stdout 및 stderr에 대한 프로그램의 출력은 정수 반환 값과 다릅니다. 프로그램은 위의 예와 같이 정수 값을 반환하는 동시에 문자열을 콘솔로 보내거나 파일이나 다른 곳으로 리디렉션 할 수 있습니다. 그것들은 상호 배타적이지 않으며 두 가지 다른 개념입니다.
David Rector

7

실행 중 : for /f %%i in ('application arg0 arg1') do set VAR=%%i오류가 발생했습니다. 현재 %% i이 (가) 예기치 않았습니다. 수정으로, 나는 위와 같이 실행해야했다.for /f %i in ('application arg0 arg1') do set VAR=%i


9
배치 파일에서 필요 %%하고 명령 줄에서 배치 파일 외부%
Jerry Jeremiah

2

답변 외에도 루프 의 설정 부분 에서 출력 리디렉션 연산자를 직접 사용할 수 없습니다 for(예 : 사용자의 stderror 출력을 숨기고 더 나은 오류 메시지를 제공하려는 경우). 대신 캐럿 문자 ( ^) 로 이스케이프해야합니다 .

for /f %%O in ('some-erroring-command 2^> nul') do (echo %%O)

참조 : 배치 스크립트의 for 루프에서 명령 출력 리디렉션


1
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION

REM Prefer backtick usage for command output reading:
REM ENABLEDELAYEDEXPANSION is required for actualized
REM  outer variables within for's scope;
REM within for's scope, access to modified 
REM outer variable is done via !...! syntax.

SET CHP=C:\Windows\System32\chcp.com

FOR /F "usebackq tokens=1,2,3" %%i IN (`%CHP%`) DO (
    IF "%%i" == "Aktive" IF "%%j" == "Codepage:" (
        SET SELCP=%%k
        SET SELCP=!SELCP:~0,-1!
    )
)
echo actual codepage [%SELCP%]

ENDLOCAL

역설 설명을위한 (plus1)
Sandburg

1

bash 쉘의 동작과 약간 유사한 명령 출력의 간단한 캡처를 위해 배치 매크로를 사용할 수 있습니다.

매크로 사용법은 간단하며 다음과 같습니다.

%$set% VAR=application arg1 arg2

파이프와도 작동합니다.

%$set% allDrives="wmic logicaldisk get name /value | findstr "Name""

매크로는 변수를 배열처럼 사용하고 각 행을 별도의 인덱스에 저장합니다.
샘플 %$set% allDrives="wmic logicaldisk에는 다음과 같은 변수가 생성됩니다.

allDrives.Len=5
allDrives.Max=4
allDrives[0]=Name=C:
allDrives[1]=Name=D:
allDrives[2]=Name=F:
allDrives[3]=Name=G:
allDrives[4]=Name=Z:
allDrives=<contains the complete text with line feeds>

그것을 사용하기 위해 매크로 자체가 어떻게 작동하는지 이해하는 것은 중요하지 않습니다.

전체 예

@echo off
setlocal

call :initMacro

%$set% ipOutput="ipconfig"
call :ShowVariable ipOutput
echo First line is %ipOutput[0]%

echo( 
%$set% driveNames="wmic logicaldisk get name /value | findstr "Name""
call :ShowVariable driveNames

exit /b

:ShowVariable
setlocal EnableDelayedExpansion
for /L %%n in (0 1 !%~1.max!) do (
    echo %%n: !%~1[%%n]!
)
echo(
exit /b

:initMacro
if "!!"=="" (
    echo ERROR: Delayed Expansion must be disabled while defining macros
    (goto) 2>nul
    (goto) 2>nul
)
(set LF=^
%=empty=%
)
(set \n=^^^
%=empty=%
)

set $set=FOR /L %%N in (1 1 2) dO IF %%N==2 ( %\n%
    setlocal EnableDelayedExpansion                                 %\n%
    for /f "tokens=1,* delims== " %%1 in ("!argv!") do (            %\n%
        endlocal                                                    %\n%
        endlocal                                                    %\n%
        set "%%~1.Len=0"                                            %\n%
        set "%%~1="                                                 %\n%
        if "!!"=="" (                                               %\n%
            %= Used if delayed expansion is enabled =%              %\n%
                setlocal DisableDelayedExpansion                    %\n%
                for /F "delims=" %%O in ('"%%~2 | findstr /N ^^"') do ( %\n%
                if "!!" NEQ "" (                                    %\n%
                    endlocal                                        %\n%
                    )                                               %\n%
                setlocal DisableDelayedExpansion                    %\n%
                set "line=%%O"                                      %\n%
                setlocal EnableDelayedExpansion                     %\n%
                set pathExt=:                                       %\n%
                set path=;                                          %\n%
                set "line=!line:^=^^!"                              %\n%
                set "line=!line:"=q"^""!"                           %\n%
                call set "line=%%line:^!=q""^!%%"                   %\n%
                set "line=!line:q""=^!"                             %\n%
                set "line="!line:*:=!""                             %\n%
                for /F %%C in ("!%%~1.Len!") do (                   %\n%
                    FOR /F "delims=" %%L in ("!line!") Do (         %\n%
                        endlocal                                    %\n%
                        endlocal                                    %\n%
                        set "%%~1[%%C]=%%~L" !                      %\n%
                        if %%C == 0 (                               %\n%
                            set "%%~1=%%~L" !                       %\n%
                        ) ELSE (                                    %\n%
                            set "%%~1=!%%~1!!LF!%%~L" !             %\n%
                        )                                           %\n%
                    )                                               %\n%
                    set /a %%~1.Len+=1                              %\n%
                )                                                   %\n%
            )                                                       %\n%
        ) ELSE (                                                    %\n%
            %= Used if delayed expansion is disabled =%             %\n%
            for /F "delims=" %%O in ('"%%~2 | findstr /N ^^"') do ( %\n%
                setlocal DisableDelayedExpansion                    %\n%
                set "line=%%O"                                      %\n%
                setlocal EnableDelayedExpansion                     %\n%
                set "line="!line:*:=!""                             %\n%
                for /F %%C in ("!%%~1.Len!") DO (                   %\n%
                    FOR /F "delims=" %%L in ("!line!") DO (         %\n%
                        endlocal                                    %\n%
                        endlocal                                    %\n%
                        set "%%~1[%%C]=%%~L"                        %\n%
                    )                                               %\n%
                    set /a %%~1.Len+=1                              %\n%
                )                                                   %\n%
            )                                                       %\n%
        )                                                           %\n%
        set /a %%~1.Max=%%~1.Len-1                                  %\n%
)                                                                   %\n%
    ) else setlocal DisableDelayedExpansion^&set argv=

goto :eof

0

5 초마다 google.com을 핑하고 현재 시간으로 결과를 기록하는 스크립트를 작성했습니다. 여기에서 변수 "commandLineStr"에 대한 출력을 찾을 수 있습니다 (지수 포함).

@echo off

:LOOPSTART

echo %DATE:~0% %TIME:~0,8% >> Pingtest.log

SETLOCAL ENABLEDELAYEDEXPANSION
SET scriptCount=1
FOR /F "tokens=* USEBACKQ" %%F IN (`ping google.com -n 1`) DO (
  SET commandLineStr!scriptCount!=%%F
  SET /a scriptCount=!scriptCount!+1
)
@ECHO %commandLineStr1% >> PingTest.log
@ECHO %commandLineStr2% >> PingTest.log
ENDLOCAL

timeout 5 > nul

GOTO LOOPSTART
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.