Windows에서 변수의 명령 결과를 얻는 방법은 무엇입니까?


132

Windows 배치 스크립트에서 변수로 명령 결과를 얻으려고합니다 ( bash 스크립트에 해당하는 bash 에서 명령 결과를 얻는 방법 참조 ). .bat 파일에서 작동하는 솔루션이 선호되지만 다른 일반적인 Windows 스크립팅 솔루션도 환영합니다.


9
존,이 매우 유용한 질문 을 찾는 것은 엄청나게 어렵습니다 . 프로그램출력Windows 배치 파일의 변수에 캡처 하는 방법
Piotr Dobrogost

3
Google은이 페이지를 3 위로 표시했습니다.
René Nyffenegger


@MichaelFreidgeim이 질문은 실제로 그 복제본이 있기 2 년 전에 요청되었지만이 질문에는 여러 개의 복제본이 있습니다. stackoverflow.com/questions/6359820/…
icc97

1
@ icc97, "가능한 복제물"은 정리할 수있는 방법입니다. 비슷한 질문을 닫고 최상의 답변을 유지하십시오. 날짜는 필수가 아닙니다. meta.stackexchange.com/questions/147643/을 참조하십시오. 설명이 필요하다고 동의하는 경우 meta.stackexchange.com/questions/281980/에서 투표 하십시오. 여러 사본이 표시되면 하나를 정식으로 선택하고 다른 사람을 닫으려면 투표해야합니다. .
Michael Freidgeim

답변:


34

모든 명령 출력을 캡처해야하는 경우 다음과 같이 배치를 사용할 수 있습니다.

@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)를보아야한다고 생각합니다.


한 줄로 답변하면 내가 가진 특정 사례를 해결할 수 있습니다. 방금 여러 줄 옵션 (또는 더 쉬운 한 줄 옵션)이 있다고 생각했습니다. 박쥐 파일의 기능은 그다지 좋지 않습니다. Java 앱을 래핑하는 bat 스크립트가 필요합니다. 주로 학급 건물.
John Meagher

매우 조심하십시오. GWT는 또한 특정 클래스 경로로 Java를 시작하기 위해 배치 파일을 사용하려고 시도했습니다 .ASCII가 아닌 문자가있는 디렉토리에 도달하자마자 끔찍하게 실패했습니다 (이 경우 내 집이었습니다). 그들은 이후 VBS로 다시 작성했습니다.
Joey

25
이것에 실용적인 용도가 있습니까? 농담 해? 이것은 다른 쉘 (내 생각에 모든 GNU / Linux 쉘)에서 항상 사용되며 매우 유용합니다.
Piotr Dobrogost

1
@PiotrDobrogost 나는 그가 말하려고했던 것은 bash 스크립트가 과거의 끔찍한 유물이라고 생각했다. ( 프로그램의 출력을 캡처하기 위해 for 루프 를 사용해야 합니까? 심각하게?) 변수를 사용해야하는 경우 PowerShell과 같은보다 현대적인 것을 사용해야합니다.
Ajedi32

3
실제로는 ... 실제로 사용됩니다. PowerShell 스크립트를 사용하여 특정 Visual Studio 경로를 찾고 싶지만 그 경로에서 필요한 것은 많은 env 변수를 설정하는 배치 파일이므로 editbin을 호출 할 수 있습니다 ... 그래서 경로를 찾아야합니다 호출 인스턴스로 다시 가져 cmd와서 거기서 실행할 수 있습니다. ... 예, 소리만큼 끔찍합니다. Visual Studio는 때때로 울고 싶어합니다. @ Ajedi32 배치 스크립트가 과거의 끔찍한 유물 이라고 말하려고 했다고 생각 합니다 . ;)
jpmc26

85

겸손 에 대한 명령은 지난 몇 년 동안 몇 가지 흥미로운 기능을 축적하고있다 :

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"

1
@PabloG의 대답과 마찬가지로 이것은이 경우 "date / t"명령의 마지막 출력 줄을 가져 오는 경우에만 작동합니다.
John Meagher

11
귀하의 답변은 이중 백분율 기호를 사용한 경우에만 작동합니다.FOR /F "delims=" %%i IN ('date /t') DO set today=%%i
Rabarberski

18
@Rabarberski : for명령 줄에 명령을 바로 입력 하면 단일을 사용합니다 %. 배치 파일에서 사용하는 경우을 사용 %%합니다.
indiv

@tardate : 다음과 같이 명령에 인수를 전달해야하는 경우 스크립트의 모양을 알려주십시오 %.for /f "delims=" %%i in ('date +%F_%H-%M-%S') do set now=%%i
dma_k

1
@degenerate 사용 된 명령이 dateCygwin에서 제공되는 경우 명령이 유효합니다 . 나는 그것을 언급해야한다는 데 동의합니다.
dma_k

24

현재 디렉토리를 얻으려면 다음을 사용할 수 있습니다.

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

그러나 더 강력한 다른 쉘로 옮기거나이 응용 프로그램을위한 응용 프로그램을 만드는 것이 좋습니다. 배치 파일의 가능성을 상당히 늘리고 있습니다.


명령에서 여러 줄을 캡처하는 변형이 있습니까?
John Meagher

6
현재 디렉토리를 얻으려면 echo % CD %
Joe

9

SET매개 변수 /P와 함께 명령 을 사용하고 출력을 지시해야합니다. 예를 들어 http://www.ss64.com/nt/set.html을 참조 하십시오 . .BAT 파일에 대해 확실하지 않은 CMD에서 작동합니다.

의견에서이 게시물로 :

이 링크에는 " Set /P _MyVar=<MyFilename.txt" 명령 이 있으며이 명령 은 _MyVar에서 첫 번째 줄로 설정 됩니다 MyFilename.txt. " myCmd > tmp.txt"with " set /P myVar=<tmp.txt" 로 사용할 수 있습니다 . 그러나 모든 출력이 아니라 출력의 첫 번째 줄만 가져옵니다.


2
이 링크에는 "/ P _MyVar = <MyFilename.txt"명령이 있으며이 명령은 _MyVar를 MyFilename.txt의 첫 번째 줄로 설정합니다. "set / P myVar = <tmp.txt"와 함께 "myCmd> tmp.txt"로 사용할 수 있습니다. 그러나 모든 출력이 아니라 출력의 첫 번째 줄만 가져옵니다.
John Meagher

이 답변은 나와 같은 초보자를위한 것입니다

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

2
나는이 접근법을 전에 보았지만 실제로 해키처럼 보인다. 또한 변수의 명령에서 마지막 출력 줄만 캡처한다는 문제가 있습니다.
John Meagher

3

FOR명령 의 결과 만 사용하십시오 . 예를 들어 (배치 파일 내부) :

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

%%I원하는 값으로 사용할 수 있습니다 . 이것처럼 : %%I.

그리고 사전에는 %%I공백이나 CR 문자가 없으며 비교에 사용할 수 있습니다!


2

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 명령 페이지 의 다른 모든 답변과 일부 파기 덕분 입니다.


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

답변을 게시 해 주셔서 감사합니다! 코드 스 니펫이 질문에 대답 할 수는 있지만 여전히 설명 등과 같은 추가 정보를 추가하는 것이 좋습니다.
j0k

2

위의 솔루션에 설명을 추가하고 싶습니다.

경로 내에 명령이 있거나 공간 또는 특수 문자가없는 명령 경로 인 경우 이러한 모든 구문이 완벽하게 작동합니다.

그러나 경로에 특수 문자가 포함 된 폴더에있는 실행 가능 명령을 사용하려고하면 명령 경로를 큰 따옴표 ( ")로 묶어야하며 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 ) .

복잡한 경로를 통해 액세스 할 수있는 이러한 종류의 명령에 대해 더 나은 솔루션을 가진 사람이 있다면 기뻐할 것입니다.


명령 앞에 접두사를 붙일 수 있습니다 CALL. 경로에 공백이 있으면 FOR / F가 작동하지 않습니다.
jeb

@ jeb : 정말 고마워요! 이제 내 코드 < CALL "%SOURCEDIR%\FOLDERBROWSE" ... "quoted parameters">가 완벽하게 작동합니다.
Gilles Maisonneuve

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=!
    )
)

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

결과는 'TXT : hola'입니다


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

명령 출력으로 수행 할 수있는 작업을 설명하는 이 http://technet.microsoft.com/en-us/library/bb490982.aspx 를 참조하십시오 .


1
이 기사에서는 리디렉션 및 관련 주제 만 다룹니다. 한 명령의 출력을 가져 와서 변수로 가져 오는 방법에 대한 질문에는 대답하지 않습니다.
John Meagher

3
그의 대답을 사용하여 나는 이것을 생각해 냈다 : git pull>0 set /P RESULTVAR=<0 편집 : 나는 여기에서 줄 바꿈을 사용하는 방법을 모른다.
RibeiroBreno
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.