4

У меня есть процесс, который мне нужно запустить в командном файле. Этот процесс производит некоторую продукцию. Мне нужно и вывести этот вывод на экран, и отправить (передать) его в другую программу.

В методе bash используется tee:

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

Есть ли аналог для Windows? Я счастлив использовать PowerShell при необходимости.

Существуют tee порты для Windows, но, по-видимому, нет эквивалента для /dev/tty , что усложняет ситуацию.


Конкретный вариант использования здесь: у меня есть программа (launch4j), которую мне нужно запустить, отображая вывод для пользователя. В то же время мне нужно уметь обнаруживать успех или неудачу в сценарии. К сожалению, эта программа не устанавливает код выхода, и я не могу заставить его сделать это. Мой текущий обходной путь включает в себя конвейер для find и поиска в выходных данных (launch4j config.xml | find "Successfully created"), однако это поглощает вывод, который мне нужно отобразить. Поэтому мне нужен какой-то способ как отобразить на экране, так и отправить выходные данные команде - и эта команда должна иметь возможность установить ERRORLEVEL (она не может работать асинхронно). Это будет использоваться в скрипте сборки, который может быть запущен на разных компьютерах.

Для этого конкретного случая требуется что-то более легкое - я не могу установить дополнительные каркасы или интерпретаторы (например, perl, как предлагается в этом ответе). Кроме того, любые коммерческие программы должны иметь лицензию, которая позволяет распространять.

6 ответов6

1

Я могу придумать несколько беспорядочный способ - использовать одну из портированных программ tee , сохранить во временный файл и затем протестировать файл с помощью команды find . Однако использование временного файла может быть нежелательным.

Если PowerShell является опцией, он фактически имеет командлет Tee-Output . Это не совсем так прямо как пример баш, но у него есть -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"

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

Почему бы просто не выполнить команду в 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"
}
0

Вы можете переписать ваш командный файл как скрипт PowerShell. PowerShell имеет Tee-Object (псевдоним Tee).

Набор параметров: File Tee-Object [-FilePath] [-Append] [-InputObject] []

Набор параметров: LiteralFile Tee-Object -LiteralPath [-InputObject] []

Набор параметров: Переменная Tee-Object -Variable [-InputObject] []

0

Я бы порекомендовал TCC/LE от JP Software: он реализует многие функции bash, включая TEE, в CMD-совместимом синтаксисе. В вашем примере это будет:

echo ee|tee con:|foo

Я проверил с помощью следующей команды

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

Здесь NL - программа, которая выдает нумерованный список, а на выходе получаются перемежающиеся ненумерованные и нумерованные строки. Задержка в 1 секунду позволила мне увидеть, что и консоль, и устройство чтения каналов одновременно получали линии.

LE версия бесплатна для частного использования.

-1

Просто поместите это в командный файл (скажем, echox.bat):

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

Затем назовите эту партию так:

echox 'c:\' dir

Он распечатает c:\ и напечатает вывод dir c:\ .

ПРИМЕЧАНИЕ: поскольку мы используем %1 , %2 , параметры должны передаваться без пробелов или внутри " " и ' ' .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .