Utilizzo di un comando Tee personalizzato per il file .bat

Sto cercando di utilizzare il codice tee scritto per un file bat, ma ho problemi ad implementarlo nel mio codice. Non voglio usare installazioni di terze parti per risolvere il problema del tee, perché voglio che il codice funzioni se modifico il mio computer in un anno e voglio eseguire nuovamente il programma.

L’ho impostato in questo modo:

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

Ho provato con un file .bat separato e ho provato a includere come funzione (preffered) nel file .bat originale senza alcun risultato con:

 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 

Sto cercando di dividere l’output in modo da poter salvare l’output della console in un file pur essendo ancora in grado di interagire con il programma in esecuzione.

Come posso ottenere il comando Tee per funzionare correttamente con il mio .bat in modo da poter dividere l’output in un file e nella console.

Il tuo tentativo di chiamare una funzione batch all’interno di una pipe fallirà sempre a causa di come funzionano le pipe di Windows – Windows istanzia entrambi i lati della pipa tramite nuove shell CMD. Vedi https://stackoverflow.com/a/8194279/1012053 per maggiori informazioni.

Quella versione di Rob van der Woude di un tee batch non può funzionare per te perché usa un FOR /F per leggere i risultati di un comando – il comando deve essere eseguito fino al completamento prima che le righe vengano lette. Ciò non funzionerà se è necessaria l’interazione dell’utente durante l’esecuzione del comando. Con quella versione di tee potresti anche semplicemente redirect l’output in un file e poi TYPE il file al termine. Ovviamente non quello che vuoi.

Ci sono trucchi in batch puri che possono avvicinarti, ma penso che ci sia ancora un problema che non può essere risolto con puro batch. Il tuo eseguibile può inserire un prompt su una riga senza emettere una nuova riga. Credo che il batch nativo puro legge sempre intere righe (tranne quando alla fine del stream). Non sono a conoscenza di un metodo batch per leggere carattere per carattere.

Leggera correzione : SET /P può leggere linee parziali di input convogliato, ma presenta limitazioni che ne impediscono l’utilizzo per una soluzione di tee di lotti robusta: non c’è modo di sapere con certezza quando ogni linea finisce. È limitato a 1021 caratteri per “linea”. Strisce i caratteri di controllo dalla fine di ogni “linea”. Non c’è modo di dire quando ha raggiunto la fine del stream di input.

Ma c’è una soluzione semplice: JScript o VBScript funziona come un campione e non richiede installazioni speciali. Ecco uno script ibrido JScript / batch che dovrebbe funzionare per te. Il JScript è scritto male con molto margine di miglioramento. Ad esempio, non vi è alcun controllo degli errori.

Salvo lo script come tee.bat . Il primo argomento obbligatorio specifica il nome del file in cui scrivere. Per impostazione predefinita, il file è sovrascritto se già esiste. Se viene fornito un secondo argomento (il valore non ha importanza), l’output viene invece aggiunto al file.

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

L’utilizzo è praticamente come ti aspetteresti.

 command.exe | tee.bat output.txt 1 

L’ultimo argomento 1 forza la modalità append. Potrebbe essere qualsiasi valore oltre a 1

È ansible mettere tutto in uno script in batch come sembra preferire.

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

Aggiornare

Per chiunque abbia un interesse accademico nello scripting in batch, ho pubblicato una versione batch nativa del tee allo script di t-shirt batch Asynchronous nativo su DosTips. Ma questo approccio ibrido è la mia soluzione di scripting preferita.