Usando um comando Tee personalizado para.ficheiro bat

estou a tentar usar o código tee escrito para um ficheiro bat, mas estou a ter dificuldade em implementá-lo no meu código. Eu não quero usar qualquer instalação de terceiros para resolver o problema do tee como eu quero que o código para funcionar se eu formatar o meu computador em um ano e quero executar o programa novamente.

Tenho-o preparado desta forma.
mycommand.exe | tee.bat -a output.txt

eu tentei com um arquivo separado {[[2]} e tentei, incluindo como uma função (pré-oferecida) no original .bat sem sucesso com:

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

estou a tentar dividir a saída para poder gravar a saída da consola num ficheiro enquanto ainda consigo interagir com o programa que está a correr.

Como posso fazer com que o comando do Tee funcione bem com o meu .bat para que eu possa dividir a saída para um arquivo e para o console.

Author: phuclv, 2012-05-23

1 answers

A sua tentativa de chamar uma função de lote dentro de um tubo irá sempre falhar devido à forma como os tubos do Windows funcionam - O Windows instancia ambos os lados do tubo através de novas conchas CMD. Ver https://stackoverflow.com/a/8194279/1012053 para mais informações.

Que a versão Rob van der Woude de um ' tee ' em lote não pode funcionar para si porque usa um FOR /F para ler os resultados de um comando - o comando tem de ser executado até à conclusão antes de quaisquer linhas serem lidas. Isso não vai funcionar se precisares. interacção do utilizador durante a execução do comando. Com essa versão do tee, você também pode simplesmente redirecionar a saída para um arquivo e então TYPE O arquivo quando terminado. Obviamente não é o que queres.

Há truques de lote puros que podem aproximar-te, mas acho que ainda há um problema que não pode ser resolvido com lote puro. Seu executável pode colocar um prompt em uma linha sem emitir uma nova linha. Eu acredito que o lote nativo puro sempre lê linhas inteiras (exceto quando no final do fluxo). Não estou ciente de um método de lote para ler personagem por personagem.

ligeira correcção - SET /P pode ler linhas parciais de entrada em piped, mas tem limitações que impedem que ele seja usado para uma solução de tee de lote robusta: não há maneira de saber com certeza quando cada linha termina. É limitado a 1021 caracteres por"linha". Retira caracteres de controlo do final de cada "linha". Não há como dizer quando chegou ao fim da entrada fluxo.

Mas há uma solução simples-JScript ou VBScript funciona como um campeão, e não requer nenhuma instalação especial. Aqui está um script JScript híbrido/batch que deve funcionar para você. O JScript é mal escrito, com muito espaço para melhorias. Por exemplo, não há verificação de erros.

Guardo o guião como tee.bat. O primeiro argumento necessário especifica o nome do arquivo para escrever. Por padrão, o arquivo é sobre-escrito se ele já existe. Se um segundo argumento é fornecido (valor não importa), então o resultado é adicionado ao arquivo em vez disso.

@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);
}

O uso é praticamente como se esperaria.

command.exe | tee.bat output.txt 1

As últimas forças de 1 argumento adicionam o modo. Pode ser qualquer valor para além de 1

É possível colocar tudo em um script de lote como você parece preferir.

@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);
}

actualizar

Para qualquer um com interesse académico em programar em lote, coloquei um lote nativo puro. version of tee at asynchronous native batch tee script over at DosTips. Mas esta abordagem híbrida é a minha solução preferida de scripting.
 20
Author: dbenham, 2017-07-04 13:27:06