Использование пользовательской команды Tee для.Bat-файл

Я пытаюсь использовать тройник код, написанный для файла bat, но у меня возникли проблемы с его реализацией в моем коде. Я не хочу использовать сторонние установки для решения проблемы tee, поскольку я хочу, чтобы код работал, если я отформатирую свой компьютер через год и хочу запустить программу снова.

у меня есть настройка таким образом:

mycommand.exe | tee.bat -a output.txt

Я пробовал с отдельной .bat файл и попытался включить в качестве функции (preffered) в исходном .bat нет avail with:

myprogram.exe | call tee -a output.txt
echo.
echo.
echo.
SET /P restart="Do you want to run again? (1=yes, 2=no): "
if "%restart%"=="1" GOTO LoopStart


::--------------------------------------------------------
::-- Function section starts below here
::--------------------------------------------------------
:tee
:: Check Windows version
IF NOT "%OS%"=="Windows_NT" GOTO Syntax
| 
:: Keep variables local
SETLOCAL

:: Check command line arguments
SET Append=0
IF /I [%1]==[-a] (
    SET Append=1
    SHIFT
)
IF     [%1]==[] GOTO Syntax
IF NOT [%2]==[] GOTO Syntax

:: Test for invalid wildcards
SET Counter=0
FOR /F %%A IN ('DIR /A /B %1 2^>NUL') DO CALL :Count "%%~fA"
IF %Counter% GTR 1 (
    SET Counter=
    GOTO Syntax
)

:: A valid filename seems to have been specified
SET File=%1

:: Check if a directory with the specified name exists
DIR /AD %File% >NUL 2>NUL
IF NOT ERRORLEVEL 1 (
    SET File=
    GOTO Syntax
)

:: Specify /Y switch for Windows 2000 / XP COPY command
SET Y=
VER | FIND "Windows NT" > NUL
IF ERRORLEVEL 1 SET Y=/Y

:: Flush existing file or create new one if -a wasn't specified
IF %Append%==0 (COPY %Y% NUL %File% > NUL 2>&1)

:: Actual TEE
FOR /F "tokens=1* delims=]" %%A IN ('FIND /N /V ""') DO (
    >  CON    ECHO.%%B
    >> %File% ECHO.%%B
)

:: Done
ENDLOCAL
GOTO:EOF


:Count
SET /A Counter += 1
SET File=%1
GOTO:EOF


:Syntax
ECHO.
ECHO Tee.bat,  Version 2.11a for Windows NT 4 / 2000 / XP
ECHO Display text on screen and redirect it to a file simultaneously
ECHO.
IF NOT "%OS%"=="Windows_NT" ECHO Usage:  some_command  ¦  TEE.BAT  [ -a ]  filename
IF NOT "%OS%"=="Windows_NT" GOTO Skip
ECHO Usage:  some_command  ^|  TEE.BAT  [ -a ]  filename
:Skip
ECHO.
ECHO Where:  "some_command" is the command whose output should be redirected
ECHO         "filename"     is the file the output should be redirected to
ECHO         -a             appends the output of the command to the file,
ECHO                        rather than overwriting the file
ECHO.
ECHO Written by Rob van der Woude
ECHO http://www.robvanderwoude.com
ECHO Modified by Kees Couprie
ECHO http://kees.couprie.org
ECHO and Andrew Cameron

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

как я могу заставить команду Tee работать должным образом с моим .bat, чтобы я мог разделить вывод как на файл, так и на консоль.

1 ответов


ваша попытка вызвать пакетную функцию в трубе всегда будет терпеть неудачу из - за того, как работают трубы Windows-Windows создает экземпляры обеих сторон трубы через новые оболочки CMD. См.https://stackoverflow.com/a/8194279/1012053 для получения дополнительной информации.

эта версия Rob van der Woude batch tee не может работать для вас, потому что она использует FOR /F для чтения результатов команды-команда должна выполняться до завершения, прежде чем будут прочитаны какие-либо строки. Это не сработает, если вам нужно взаимодействие с пользователем во время выполнения команды. С этой версией tee вы можете просто перенаправить вывод в файл, а затем TYPE файл, когда закончите. Очевидно, не то, что ты хочешь.

есть чистые пакетные трюки, которые могут приблизить вас, но я думаю, что есть еще одна проблема, которая не может быть решена с чистой партией. Ваш исполняемый файл может поместить приглашение в строку без выдачи новой строки. Я считаю, что pure native batch всегда читает целые строки (за исключением случаев, когда конец потока). Я не знаю пакетного метода для чтения символа за символом.

небольшая коррекция - SET /P смогите прочитать частично линии piped входного сигнала, но оно имеет ограничения которые предотвращают его от быть использованным для робастного разрешения тройника серии: никакой путь знать наверняка когда каждая линия кончается. Он ограничен 1021 символами на "строку". Он удаляет символы управления из конца каждой "строки". Невозможно сказать, когда это произошло. дошел до конца входного потока.

но есть простое решение-JScript или VBScript работает как чемпион и не требует каких-либо специальных установок. Вот гибридный сценарий JScript / batch, который должен работать для вас. JScript плохо написан с большим количеством возможностей для улучшения. Например, отсутствует проверка ошибок.

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

@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment

::--- Batch section within JScript comment that calls the internal JScript ----
@echo off
cscript //E:JScript //nologo "%~f0" %*
exit /b

----- End of JScript comment, beginning of normal JScript  ------------------*/
var fso = new ActiveXObject("Scripting.FileSystemObject");
var mode=2;
if (WScript.Arguments.Count()==2) {mode=8;}
var out = fso.OpenTextFile(WScript.Arguments(0),mode,true);
var chr;
while( !WScript.StdIn.AtEndOfStream ) {
  chr=WScript.StdIn.Read(1);
  WScript.StdOut.Write(chr);
  out.Write(chr);
}

использование в значительной степени, как и следовало ожидать.

command.exe | tee.bat output.txt 1

последние 1 аргумент добавить сил. Это может быть любое значение, кроме 1

можно поместить все в один пакетный скрипт, как вам кажется предпочитать.

@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment

::--- Batch section within JScript comment ----------------------------
@echo off

::This block of code handles the TEE by calling the internal JScript code
if "%~1"=="_TEE_" (
  cscript //E:JScript //nologo "%~f0" %2 %3
  exit /b
)

::The rest of your batch script goes here

::This pipes to TEE in append mode
mycommand.exe | "%~f0" _TEE_ output.txt 1

exit /b

----- End of JScript comment, beginning of normal JScript  ------------------*/
var fso = new ActiveXObject("Scripting.FileSystemObject");
var mode=2;
if (WScript.Arguments.Count()==2) {mode=8;}
var out = fso.OpenTextFile(WScript.Arguments(0),mode,true);
var chr;
while( !WScript.StdIn.AtEndOfStream ) {
  chr=WScript.StdIn.Read(1);
  WScript.StdOut.Write(chr);
  out.Write(chr);
}

обновление

для тех, кто имеет академический интерес к пакетным сценариям, я опубликовал чистую нативную пакетную версию tee в асинхронный собственный пакетный tee-скрипт на DosTips. Но этот гибридный подход является моим предпочтительным скриптовым решением.