batch-file - Visualizzazione dell'output del prompt dei comandi di Windows e reindirizzamento a un file



13 Answers

Per espandere la risposta di davor , è possibile utilizzare PowerShell in questo modo:

powershell "dir | tee test.txt"

Se stai cercando di reindirizzare l'output di un exe nella directory corrente, devi usare .\ Sul nome del file, ad esempio:

powershell ".\something.exe | tee test.txt"
batch-file cmd stdout tee

Come posso eseguire un'applicazione della riga di comando nel prompt dei comandi di Windows e avere l'output sia visualizzato che reindirizzato su un file nello stesso momento?

Se, ad esempio, dovessi eseguire il comando dir > test.txt , ciò reindirizzerebbe l'output a un file chiamato test.txt senza visualizzare i risultati.

Come posso scrivere un comando per visualizzare l'output e reindirizzare l'output su un file nel prompt dei comandi di Windows, in modo simile al comando tee su Unix?




Controlla questo: wintee

Non c'è bisogno di cygwin.

Ho incontrato e segnalato alcuni problemi però.

Inoltre potresti controllare http://unxutils.sourceforge.net/ perché contiene tee (e non c'è bisogno di cygwin), ma http://unxutils.sourceforge.net/ attenzione che gli EOL di output sono simili a UNIX qui.

Ultimo, ma non meno importante, è che se hai PowerShell, potresti provare Tee-Object. Digitare get-help tee-object nella console di PowerShell per ulteriori informazioni.




Sfortunatamente non esiste una cosa del genere.

Le applicazioni della console Windows hanno un unico handle di output. (Bene, ci sono due STDOUT , STDERR ma non importa qui) > reindirizza l'output normalmente scritto sull'handle della console a un handle di file.

Se si desidera disporre di una sorta di multiplexing, è necessario utilizzare un'applicazione esterna a cui è possibile deviare l'output. Questa applicazione può quindi scrivere nuovamente su un file e sulla console.




Questo funziona, anche se è un po 'brutto:

dir >_ && type _ && type _ > a.txt

È un po 'più flessibile di alcune delle altre soluzioni, in quanto funziona statement-by-statement in modo da poterlo usare anche per aggiungere. Lo uso abbastanza nei file batch per registrare e visualizzare i messaggi:

ECHO Print line to screen and log to file.  >_ && type _ && type _ >> logfile.txt

Sì, puoi semplicemente ripetere l'istruzione ECHO (una volta per lo schermo e la seconda volta reindirizzare al file di log), ma sembra altrettanto brutto ed è un po 'un problema di manutenzione. Almeno in questo modo non è necessario apportare modifiche ai messaggi in due punti.

Si noti che _ è solo un breve nome file, quindi è necessario assicurarsi di eliminarlo alla fine del file batch (se si sta utilizzando un file batch).




Sono d'accordo con Brian Rasmussen, la porta unxutils è il modo più semplice per farlo. Nella sezione File batch delle sue pagine di scripting, Rob van der Woude fornisce una grande quantità di informazioni sull'uso dei comandi MS-DOS e CMD. Ho pensato che potrebbe avere una soluzione nativa al tuo problema e dopo aver scavato da queste parti ho trovato TEE.BAT , che sembra essere proprio questo, un'implementazione in linguaggio batch di MS-DOS del tee. È un file batch piuttosto complesso e la mia inclinazione sarebbe comunque quella di utilizzare la porta unxutils.




Se hai cygwin nel tuo percorso di ambiente Windows puoi usare:

 dir > a.txt | tail -f a.txt



Stavo anche cercando la stessa soluzione, dopo un piccolo tentativo, sono riuscito a farlo in Prompt dei comandi. Ecco la mia soluzione:

@Echo off
for /f "Delims=" %%a IN (xyz.bat) do (
%%a > _ && type _ && type _ >> log.txt
)
@Echo on

Cattura anche qualsiasi comando PAUSE.




Ecco un esempio di ciò che ho usato in base a una delle altre risposte

@echo off
REM SOME CODE
set __ERROR_LOG=c:\errors.txt
REM set __IPADDRESS=x.x.x.x

REM Test a variable
if not defined __IPADDRESS (
     REM Call function with some data and terminate
     call :TEE %DATE%,%TIME%,IP ADDRESS IS NOT DEFINED
     goto :EOF
)

REM If test happens to be successful, TEE out a message and end script.
call :TEE Script Ended Successful
goto :EOF


REM THE TEE FUNCTION
:TEE
for /f "tokens=*" %%Z in ("%*") do (
     >  CON ECHO.%%Z
     >> "%__ERROR_LOG%" ECHO.%%Z
     goto :EOF
)



So che questo è un argomento molto vecchio, ma nelle risposte precedenti non c'è una piena implementazione di un Tee in tempo reale scritto in Batch. La mia soluzione qui sotto è uno script ibrido Batch-JScript che usa la sezione JScript solo per ottenere l'output dal comando pipe, ma l'elaborazione dei dati viene eseguita nella sezione Batch. Questo approccio ha il vantaggio che qualsiasi programmatore Batch può modificare questo programma per soddisfare esigenze specifiche. Questo programma inoltre elabora correttamente l'output del comando CLS prodotto da altri file Batch, ovvero cancella lo schermo quando viene rilevato l'output del comando CLS.

@if (@CodeSection == @Batch) @then


@echo off
setlocal EnableDelayedExpansion

rem APATee.bat: Asynchronous (real time) Tee program, Batch-JScript hybrid version
rem Antonio Perez Ayala

rem The advantage of this program is that the data management is written in Batch code,
rem so any Batch programmer may modify it to fit their own needs.
rem As an example of this feature, CLS command is correctly managed

if "%~1" equ "" (
   echo Duplicate the Stdout output of a command in the screen and a disk file
   echo/
   echo anyCommand ^| APATee teeFile.txt [/A]
   echo/
   echo If /A switch is given, anyCommand output is *appended* to teeFile.txt
   goto :EOF
)

if "%2" equ ":TeeProcess" goto TeeProcess

rem Get the output of CLS command
for /F %%a in ('cls') do set "cls=%%a"

rem If /A switch is not provided, delete the file that receives Tee output
if /I "%~2" neq "/A" if exist %1 del %1

rem Create the semaphore-signal file and start the asynchronous Tee process
echo X > Flag.out
if exist Flag.in del Flag.in
Cscript //nologo //E:JScript "%~F0" | "%~F0" %1 :TeeProcess
del Flag.out
goto :EOF

:TeeProcess
   rem Wait for "Data Available" signal
   if not exist Flag.in goto TeeProcess
   rem Read the line sent by JScript section
   set line=
   set /P line=
   rem Set "Data Read" acknowledgement
   ren Flag.in Flag.out
   rem Check for the standard "End Of piped File" mark
   if "!line!" equ ":_EOF_:" exit /B
   rem Correctly manage CLS command
   if "!line:~0,1!" equ "!cls!" (
      cls
      set "line=!line:~1!"
   )
   rem Duplicate the line in Stdout and the Tee output file
   echo(!line!
   echo(!line!>> %1
goto TeeProcess


@end


// JScript section

var fso = new ActiveXObject("Scripting.FileSystemObject");
// Process all lines of Stdin
while ( ! WScript.Stdin.AtEndOfStream ) {
   // Read the next line from Stdin
   var line = WScript.Stdin.ReadLine();
   // Wait for "Data Read" acknowledgement
   while ( ! fso.FileExists("Flag.out") ) {
      WScript.Sleep(10);
   }
   // Send the line to Batch section
   WScript.Stdout.WriteLine(line);
   // Set "Data Available" signal
   fso.MoveFile("Flag.out", "Flag.in");
}
// Wait for last "Data Read" acknowledgement
while ( ! fso.FileExists("Flag.out") ) {
      WScript.Sleep(10);
}
// Send the standard "End Of piped File" mark
WScript.Stdout.WriteLine(":_EOF_:");
fso.MoveFile("Flag.out", "Flag.in");



Questa è una variazione rispetto a una answer precedente di MTS, tuttavia aggiunge alcune funzionalità che potrebbero essere utili ad altri. Ecco il metodo che ho usato:

  • Un comando è impostato come variabile, che può essere utilizzato in un secondo momento nel codice, per l'output nella finestra di comando e aggiunto a un file di registro, utilizzando set _Temp_Msg_Cmd=
    • il comando è stato redirection con il carattere carota ^ modo che i comandi non vengano valutati inizialmente
  • Viene creato un file temporaneo con un nome file simile al file batch da eseguire chiamato %~n0_temp.txt che utilizza la sintassi dell'estensione del parametro della riga di comando %~n0 per ottenere il nome del file batch.
  • L'output viene aggiunto a un file di registro separato %~n0_log.txt

Ecco la sequenza di comandi:

  1. I messaggi di output e di errore vengono inviati al file temporaneo ^> %~n0_temp.txt 2^>^&1
  2. Il contenuto del file temporaneo è quindi entrambi:
    • aggiunto al file di registro ^& type %~n0_temp.txt ^>^> %~n0_log.txt
    • ^& type %~n0_temp.txt alla finestra di comando ^& type %~n0_temp.txt
  3. Il file temporaneo con il messaggio viene cancellato ^& del /Q /F %~n0_temp.txt

Ecco l'esempio:

set _Temp_Msg_Cmd= ^> %~n0_temp.txt 2^>^&1 ^& type %~n0_temp.txt ^>^> %~n0_log.txt ^& type %~n0_temp.txt ^& del /Q /F %~n0_temp.txt

In questo modo, il comando può essere semplicemente aggiunto dopo i comandi successivi in ​​un file batch che sembra molto più pulito:

echo test message %_Temp_Msg_Cmd%

Questo può essere aggiunto anche alla fine di altri comandi. Per quanto posso dire funzionerà quando i messaggi hanno più linee. Ad esempio il seguente comando emette due righe se c'è un messaggio di errore:

net use M: /D /Y %_Temp_Msg_Cmd%




Seguire gli aiuti se si desidera che qualcosa venga realmente visualizzato sullo schermo, anche se il file batch è stato reindirizzato a un file. Il dispositivo CON può essere utilizzato anche se reindirizzato su un file

Esempio:

ECHO first line on normal stdout. maybe redirected
ECHO second line on normal stdout again. maybe redirected
ECHO third line is to ask the user. not redirected  >CON
ECHO fourth line on normal stdout again. maybe redirected

Vedi anche una buona descrizione di reindirizzamento: http://www.p-dd.com/chapter7-page14.html




Funziona in tempo reale ma è anche un po 'brutto e la performance è lenta. Non ben collaudati:

@echo off
cls
SET MYCOMMAND=dir /B
ECHO File called 'test.bat' > out.txt
for /f "usebackq delims=" %%I in (`%MYCOMMAND%`) do (
  ECHO %%I
  ECHO %%I >> out.txt
) 
pause



Proprio come Unix

dir | tee a.txt

funziona su Windows XP, richiede mksnt installato

Si visualizza sul promt e si aggiunge al file




Related