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





parametri passare (24)


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");

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?




Come posso visualizzare e reindirizzare l'output su un file. Supponiamo che se utilizzo il comando dos, dir> test.txt, questo comando reindirizzerà l'output sul file test.txt senza visualizzare i risultati. come scrivere un comando per visualizzare l'output e reindirizzare l'output su un file utilizzando DOS, prompt dei comandi di Windows, non in UNIX / LINUX.

È possibile trovare utili questi comandi in biterscripting ( http://www.biterscripting.com ).

var str output
lf > $output
echo $output                            # Will show output on screen.
echo $output > "test.txt"               # Will write output to file test.txt.
system start "test.txt"                 # Will open file test.txt for viewing/editing.



Una semplice applicazione per console C # potrebbe fare il trucco:

using System;
using System.Collections.Generic;
using System.IO;

namespace CopyToFiles
{
    class Program
    {
        static void Main(string[] args)
        {
            var buffer = new char[100];
            var outputs = new List<TextWriter>();

            foreach (var file in args)
                outputs.Add(new StreamWriter(file));

            outputs.Add(Console.Out);

            int bytesRead;
            do
            {
                bytesRead = Console.In.ReadBlock(buffer, 0, buffer.Length);
                outputs.ForEach(o => o.Write(buffer, 0, bytesRead));
            } while (bytesRead == buffer.Length);

            outputs.ForEach(o => o.Close());
        }
    }
}

Per usarlo basta inserire il comando source nel programma e fornire il percorso di tutti i file su cui si desidera duplicare l'output. Per esempio:

dir | CopyToFiles files1.txt files2.txt 

Visualizzerà i risultati di dir e memorizzerà i risultati sia in files1.txt che files2.txt.

Si noti che non c'è molto (nulla!) In termini di gestione degli errori di cui sopra, e il supporto di più file potrebbe non essere effettivamente richiesto.




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).




dir 1>a.txt 2>&1 | type a.txt

Ciò contribuirà a reindirizzare sia STDOUT che STDERR




Sono stato in grado di trovare una soluzione / soluzione alternativa per reindirizzare l'output a un file e quindi alla console:

dir > a.txt | type a.txt

dove dir è il comando su cui l'output deve essere reindirizzato, a.txt un file in cui archiviare l'output.







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




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.




Mi piacerebbe espandere un po 'l' eccellente risposta di Saxon Druce.

Come detto, puoi reindirizzare l'output di un eseguibile nella directory corrente in questo modo:

powershell ".\something.exe | tee test.txt"

Tuttavia, questo registra solo stdout su test.txt . Non registra anche stderr .

La soluzione ovvia sarebbe quella di usare qualcosa del genere:

powershell ".\something.exe 2>&1 | tee test.txt"

Tuttavia, questo non funzionerà per tutti i file something.exe . Alcuni something.exe s interpreteranno il 2>&1 come argomento e falliranno. La soluzione corretta è invece di avere solo apostrofi attorno a something.exe e sono switch e argomenti, in questo modo:

powershell ".\something.exe --switch1 --switch2 … arg1 arg2 …" 2>&1 | tee test.txt



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.




@ tori3852

l'ho trovato

dir > a.txt | type a.txt

non ha funzionato (prima alcune righe di elenco di directory solo - sospetto di un processo di forking di processo e la seconda parte, il comando di tipo terminato prima della fine della lista terribile?), quindi ho usato:

dir > z.txt && type z.txt

che ha fatto - comandi sequenziali, uno completo prima che inizi il secondo.




Io uso una subroutine batch con un'istruzione "for" per ottenere il comando in output una riga alla volta e scrivere la riga su un file e inviarla alla console.

@echo off
set logfile=test.log

call :ExecuteAndTee dir C:\Program Files

Exit /B 0

:ExecuteAndTee
setlocal enabledelayedexpansion
echo Executing '%*'
  for /f "delims=" %%a in ('%* 2^>^&1') do (echo.%%a & echo.%%a>>%logfile%)
endlocal
Exit /B 0



Proprio come Unix

dir | tee a.txt

funziona su Windows XP, richiede mksnt installato

Si visualizza sul promt e si aggiunge al file




@echo on

set startDate=%date%
set startTime=%time%

set /a sth=%startTime:~0,2%
set /a stm=1%startTime:~3,2% - 100
set /a sts=1%startTime:~6,2% - 100


fullprocess.bat > C:\LOGS\%startDate%_%sth%.%stm%.%sts%.LOG | fullprocess.bat

Ciò creerà un file di registro con il datetime corrente e le linee della console potranno essere utilizzate durante il processo




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"



Installo perl sulla maggior parte delle mie macchine quindi una risposta usando perl: tee.pl

my $file = shift || "tee.dat";
open $output, ">", $file or die "unable to open $file as output: $!";
while(<STDIN>)
{
    print $_;
    print $output $_;
}
close $output;

dir | perl tee.pl o dir | perl tee.pl dir.bat

grezzo e non testato.




Un'alternativa è quella di aggiungere stdout a stderr all'interno del tuo programma:

in java:

System.setOut(new PrintStream(new TeeOutputStream(System.out, System.err)));

Quindi, nel file batch dos: java program > log.txt

Lo stdout andrà al file di log e lo stderr (stessi dati) verrà mostrato sulla console.




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%




invia l'output alla console, aggiungi al log della console, elimina l'output dal comando corrente

dir  >> usb-create.1 && type usb-create.1 >> usb-create.log | type usb-create.1 && del usb-create.1



mtee è una piccola utility che funziona molto bene per questo scopo. È gratuito, la fonte è aperta e funziona.

Puoi trovarlo su http://www.commandline.co.uk .

Utilizzato in un file batch per visualizzare l'output E creare un file di registro simultaneamente, la sintassi è simile alla seguente:

    someprocess | mtee /+ mylogfile.txt

Dove / + significa aggiungere l'output.

Ciò presuppone che hai copiato mtee in una cartella che si trova nel PERCORSO, ovviamente.




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
)



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



< command > |& tee filename # questo creerà un file "nomefile" con stato di comando come contenuto, Se un file esiste già rimuoverà il contenuto esistente e scriverà lo stato del comando.

< command > | tee >> filename < command > | tee >> filename # aggiungerà lo stato al file ma non stampa lo stato del comando su standard_output (schermo).

Voglio stampare qualcosa usando "echo" sullo schermo e aggiungere i dati eco a un file

echo "hi there, Have to print this on screen and append to a file" 




batch-file cmd stdout tee