Windows의 명령 행에서 파이프 및 디스플레이 출력을 모두 어떻게 할 수 있습니까?


4

배치 파일 내에서 실행 해야하는 프로세스가 있습니다. 이 프로세스는 일부 출력을 생성합니다. 이 출력을 화면에 표시 하고 다른 프로그램으로 보내 (파이프)해야합니다.

bash는 방법을 사용합니다 tee:

echo 'ee' | tee /dev/tty | foo

Windows에 해당하는 것이 있습니까? 필요한 경우 PowerShell을 사용하게되어 기쁩니다.

teeWindows 용 포트 가 있지만에 해당하는 포트가 없어서 /dev/tty문제가 복잡합니다.


구체적인 유스 케이스는 다음과 같습니다. 실행 해야하는 프로그램 (launch4j)이 있으며 사용자에게 출력을 표시합니다. 동시에 스크립트에서 성공 또는 실패를 감지 할 수 있어야합니다. 불행히도이 프로그램은 종료 코드를 설정하지 않으므로 강제로 설정할 수 없습니다. 현재 해결 방법은으로 파이핑 find하여 출력 ( launch4j config.xml | find "Successfully created") 을 검색하는 것입니다. 그러나 표시 해야하는 출력을 삼 킵니다. 따라서, 나는 화면에 모두 표시 할 수있는 방법이 필요하고, 명령에 OUPUT을 보내 - 하고 이 명령을 설정 할 수 있어야한다 ERRORLEVEL(이것은 비동기 적으로 실행할 수 없습니다). 이것은 많은 다른 머신에서 실행될 수있는 빌드 스크립트에서 사용됩니다.

이 특별한 경우에는 가벼운 것이 필요합니다-추가 프레임 워크 또는 인터프리터를 설치할 수 없습니다 (예 : 이 답변 에서 제안 된 perl ). 또한 모든 상용 프로그램에는 재배포를 허용하는 라이센스가 있어야합니다.


코드를 컴파일하고 실행 파일에 대한 링크를 제공하면 내 대답이 더 수용 가능합니까? 컴파일러에 액세스 할 수 없거나 직접하고 싶지 않으면 원하는 경우 할 수 있습니다.
BenjiWiebe

답변:


1

이 코드를 컴파일하고 다음과 같이 사용할 수 echo something | mytee | foo있습니다.
Windows가 stderr/를 처리하는 방법을 모르기 때문에 작동하는지 잘 모르겠지만 stdout작동 할 수 있습니다.

#include <stdio.h>
int main()
{
    int c;
    while((c = fgetc(stdin)) != EOF)
    {
        printf("%c", c);
        fprintf(stderr, "%c", c);
    }
    return 0;
}

1

내가 생각할 수있는 다소 지저분한 방법은 이식 된 tee프로그램 중 하나를 사용 하고 임시 파일에 저장 한 다음 파일을 테스트하는 것입니다 find. 그러나 임시 파일을 사용하는 것은 바람직하지 않습니다.

PowerShell이 ​​옵션 인 경우 실제로 Tee-Outputcmdlet이 있습니다. bash 예제만큼 직접적이지 않지만 -Variable출력을 변수에 저장 하는 옵션이 있습니다.

# save result in $LastOutput and also display it to the console
echo "some text" | Tee-Output -Variable LastOutput

# search $LastOutput for a pattern, using Select-String
# instead of find to keep it within PowerShell
$Result = $LastOutput | Select-String -Quiet "text to find"

# $Result should contain either true or false now
# this is the equivalent of batch "if errorlevel 1"
if ($Result -eq $True) {
    # the string exists in the output
}

더 일반적인 질문에 대답하기 위해 변수를 다른 프로그램에 파이프하여 설정할 수도 $LastExitCode있습니다. 기본 명령 줄에서 호출 할 수있는 단일 라이너로 :powershell -c "echo text | Tee-Object -Variable Result; $Result | foo"


가능한 경우 기본 (PowerShell이 ​​아닌) 명령 줄 내에서 임시 파일 없이이 작업을 수행하는 방법을 찾고 있습니다.

* nix에서 스크립트에서 항상 I teestderr; 에 방법이 tee모두 stderrstdoutPowerShell의가, 또는 Windows / PowerShell은 그 개념이하지 않는 이유는 무엇입니까?
BenjiWiebe

@BenjiWiebe /dev/stderr맞습니까? 내가 아는 한 Windows에는 존재하지 않습니다. 명명 된 파이프가있는 것이 가능하지만이 목적을 위해 프로그램을 작성하지 않도록 노력하고 있습니다!
Bob

1
프로그래밍 방식으로 말하자면 /dev/stderr커널 개념으로 파일을 디스크립터로 리디렉션합니다 stderr. Windows에서 stderr(NOT /dev/stderr) 로 리디렉션하는 방법이 없습니까?
BenjiWiebe

내가 무슨 생각에 대한 설명은 내 대답을 참조하십시오 (그리고 그것은 작동 할 수도 있습니다!)
BenjiWiebe

1

PowerShell에서 명령을 실행 Invoke-Command하고 결과를 변수로 캡처하는 것이 어떻습니까? 변수가있을 경우 변수를 검색하여 결과를 얻은 다음 모든 출력을 콘솔에 표시합니다.

출력을 캡처 할 테스트 파일은 다음 텍스트 (C; \ Temp \ OutputTest.txt)가있는 메모장입니다.

blahlbalsdfh
abalkshdiohf32iosknfsda
afjifwj93f2ji23fnsfaijfafds
fwjifej9f023f90f3nisfadlfasd
fwjf9e2902fjf3jifdsfajofsda
jfioewjf0990f
Successfully Created
fsjfd9waf09jf329j0f3wjf90awfjw0afwua9

귀하의 경우에는 {& "Launch4j" config.xml}내가 믿는 것처럼 명령을 호출 하지만 내 예는 다음과 같습니다.

Invoke-Command -ScriptBlock {Get-Content C:\temp\OutputTest.txt} | foreach {
$_;
if ($_ -match "successfully created") {$flag = $true}
}
if ($flag) {
"do whatever"
}

그것이 바로 내가 한 일이며, 본인의 답변에서 설명한 내용입니다.이 답변에 더 많은 정보가 추가됩니까?

아, 프로세스가 약간 다릅니다 ( Tee-Object직접 사용하지 않고 나중에 수동으로 출력을 인쇄합니다). 그런 다음이 접근법의 단점 중 하나는 전체 출력을 캡처 한 다음 한 번에 표시해야한다는 것입니다. 즉 프로세스가 실행되는 동안 사용자는 출력이 끝나고 나서야 출력을 볼 수 없습니다. 단기 실행 작업에는 허용되지만 더 긴 작업에는 적합하지 않습니다.

각 줄을 출력하고 동시에 확인하여 메시지를 찾으면 플래그를 설정하도록 편집되었습니다. 메시지를 기반으로 명령을 실행하면 출력이 완료 될 때까지 명령이 실행되지 않으므로 질문에 따라 비동기 적으로 실행할 수 없습니다. 그러나 PowerShell에서 Start-Job을 사용하여 필요한 경우 현재 프로세스 외부에서 실행할 수 있다면 출력이 완료되면 Get-Job으로 작업 상태를 확인하십시오.
Shawn Melton

0

JP Software의 TCC / LE 를 추천 합니다. TEE를 포함한 bash의 많은 기능을 CMD 호환 구문으로 구현합니다. 귀하의 예에서는 다음과 같습니다.

echo ee|tee con:|foo

다음 명령으로 테스트했습니다.

for /l %n in (1,1,10) do ( echo %n %+ delay)|tee con:|nl.

여기서 NL은 번호 매기기 목록을 제공하는 프로그램이며 출력은 번호가 매겨지지 않은 번호가 매겨진 줄에 산재되어 있습니다. 1 초 지연으로 콘솔과 파이프 리더 모두 동시에 라인을 수신하고 있음을 알 수있었습니다.

LE 버전은 개인용으로 무료입니다.


불행히도, 이것은 내 특정 작업에 너무 지나친 것입니다. POSIX 에뮬레이션 레이어를 사용하려면 MSYS 또는 cygwin을 사용하면됩니다. 또한 tee자체적으로 도움이되지 않습니다. 이는 tty 또는 출력 장치를 파일처럼 마치 POSIX가 제공하는 것이지 tee명령 이 아닌 tty 또는 출력 장치로 리디렉션하는 기능 입니다.
Bob

TCC는 echo ee|tee con:|foo다음과 같이 할 수 있습니다.- 다음 명령으로 테스트했습니다 for /l %n in (1,1,10) do ( echo %n %+ delay)|tee con:|nl. 여기서 NL은 번호 매기기 목록을 제공하는 프로그램이며 출력은 번호가 매겨지지 않은 번호가 매겨진 줄에 산재되어 있습니다. 1 초 지연으로 콘솔과 파이프 리더 모두 동시에 라인을 수신하고 있음을 알 수있었습니다. 과잉이라고 생각해서 죄송합니다. TCC가 없을 것입니다.
AFH

맞습니다-답변에 포함시킬 수 있다면 좋을 것입니다 (콘솔을 참조하는 방법을 제공한다는 것이 즉시 명확하지는 않습니다). 다른 사람들이 사용할 수 있도록 버전 제어를 위해 빌드 스크립트를 작성하려고 시도하고 있기 때문에 여전히 케이스에 과도하게 사용되므로 타사 소프트웨어를 최소화하고 싶습니다 (라이센스가 허용하는 경우 redis). Benji의 대답과 같은 작은 바이너리는 허용되며 설치해야 할 전체 명령 해석기가 너무 많습니다. 그래도 다른 사람들에게 유용 할 수 있습니다.

좋은 지적. 제안한대로 답변을 업데이트했으며 Benji의 솔루션이 특정 요구에 적합 할 수 있음을 알 수 있지만 테스트 할 것이라고 생각 fflush(NULL);했으며 fprintf () 행 뒤에 추가해야한다는 것을 알았 습니다. 실시간으로 출력을 볼 수 있습니다. 상업 환경에있는 경우 적절한 라이센스를 구매하지 않으면 TCC를 사용할 수 없습니다.
AFH

0

배치 파일을 PowerShell 스크립트로 다시 작성할 수 있습니다. PowerShell에는 Tee-Object(로 별칭이 지정됨 Tee)이 있습니다.

매개 변수 세트 : File Tee-Object [-FilePath] [-Append] [-InputObject] []

매개 변수 세트 : LiteralFile Tee-Object -LiteralPath [-InputObject] []

파라미터 세트 : 변수 Tee-Object -Variable [-InputObject] []


그렇습니다. 자체 답변에 설명 된 프로세스로 결과가 끝났습니다. 이 답변에 더 많은 정보가 추가됩니까?

-1

이것을 배치 파일에 넣으십시오 (라고 말하십시오 echox.bat).

@echo off
echo %1
echo %1|%2

그런 다음 배치를 다음과 같이 호출하십시오.

echox 'c:\' dir

c:\출력을 인쇄하고 인쇄합니다 dir c:\.

참고 : 우리는 사용으로 %1, %2매개 변수는 공백없이 또는 내 전달해야 " "하고 ' '.


1
임의의 문제에 적용되는 경우, 명령을 두 번 실행하여 콘솔에 출력을 처음 인쇄하고 두 번째로 대상에 파이핑합니다. 명령 자체가 하드 디스크의 파일 상태 등을 변경하는 경우에는 작동하지 않을 수 있습니다.
Thomas Weller

@ThomasW, 명령을 두 번 실행하지 않습니다. 보시다시피, 먼저 화면에 매개 변수를 echo %1인쇄 %1하고 두 번째 echo%1매개 변수를 %2프로그램으로 보냅니다 . 물론 몇 가지 제한 사항이 있지만 일반적으로 문제를 해결합니다.
Jet
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.