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.