Come echo e invio l'output della console a un file in uno script bat?


136

Ho uno script batch che esegue un'attività e invia l'output a un file di testo. C'è un modo per mostrare l'output anche nella finestra della console?

Per esempio:

c:\Windows>dir > windows-dir.txt

C'è un modo per avere l'output di dirdisplay nella finestra della console e metterlo nel file di testo?


Qui sono spiegati i reindirizzamenti che puoi effettuare e alcuni esempi. <br> Spero che sia d'aiuto :)
emoSTN,


Si prega di notare, @Vadzim, che una domanda posta il 2 febbraio 2009 alle 16:38 non può essere considerata un duplicato di una domanda posta quasi tre mesi dopo il 28 aprile 2009 alle 06:32.
Compo il

Risposte:


216

No, non puoi con il puro reindirizzamento.
Ma con alcuni trucchi (come tee.bat ) puoi farlo.

Provo a spiegare un po 'il reindirizzamento.

Si reindirizza uno dei dieci flussi con > file o <file
Non è importante, se il reindirizzamento è prima o dopo il comando, quindi queste due righe sono quasi uguali.

dir > file.txt
> file.txt dir

Il reindirizzamento in questo esempio è solo una scorciatoia per 1> , ciò significa che il flusso 1 (STDOUT) verrà reindirizzato.
In questo modo puoi reindirizzare qualsiasi stream anteponendo il numero come 2> err.txt ed è anche possibile reindirizzare più stream in una riga.

dir 1> files.txt 2> err.txt 3> nothing.txt

In questo esempio l '"output standard" andrà in files.txt, tutti gli errori saranno in err.txt e lo stream3 andrà in nothing.txt (DIR non usa lo stream 3).
Stream0 è STDIN
Stream1 è STDOUT
Stream2 è STDERR
Stream3-9 non utilizzati

Ma cosa succede se provi a reindirizzare più volte lo stesso stream?

dir > files.txt > two.txt

"Ce ne può essere solo uno", ed è sempre l'ultimo!
Quindi è uguale a dir> two.txt

Ok, c'è un'ulteriore possibilità, reindirizzare uno stream a un altro stream.

dir 1>files.txt 2>&1 

2> & 1 reindirizza stream2 su stream1 e 1> files.txt reindirizza tutto su files.txt .
L'ordine è importante qui!

dir ... 1>nul 2>&1
dir ... 2>&1 1>nul

sono diversi. Il primo reindirizza tutto (STDOUT e STDERR) su NUL,
ma la seconda riga reindirizza STDOUT su NUL e STDERR sullo STDOUT "vuoto".

Come conclusione, è ovvio perché gli esempi di Otávio Décio e andynormancx non possono funzionare.

command > file >&1
dir > file.txt >&2

Entrambi provano a reindirizzare stream1 due volte, ma "Ce ne può essere solo uno" ed è sempre l'ultimo.
Quindi ottieni

command 1>&1
dir 1>&2

E nel primo esempio il reindirizzamento di stream1 a stream1 non è consentito (e non molto utile).

Spero che sia d'aiuto.


24
Quindi è impossibile con la shell nativa di Windows
fantastico

7
@fantastory È possibile, vedere questa ottima soluzione del batch
jeb

97
Non riesco a credere di aver letto l'intero post per scoprire che tutto può essere sintetizzato come "No".
Charles McKelvey,

1
Che dire del secondo meccanismo "gestire la duplicazione"? Ho sperimentato 3<&2(notare LT invece di GT), e poi 3>errors.txt. Ma questo è finito male - tutta la successiva uscita stderr è stata catturata errors.txt(cioè - anche da altri comandi!).
Tomasz Gandor,

Potresti usare for /f "delims=" %%v in ('dir') do echo %%v>>file.txtperò.
scriptmastere02

32

Usa la versione Windows del comando tee UNIX (reperibile su http://unxutils.sourceforge.net ) in questo modo:

mycommand > tee outpu_file.txt

Se è necessario anche l'output STDERR, utilizzare quanto segue.
L' 2>&1combina l'output STDERR in STDOUT (flusso primario).

mycommand 2>&1 | tee output_file.txt

3
Il PowerShell Tee-Object offre funzionalità simili. Get-Process | Tee-Object -file c: \ scripts \ test.txt
Kevin Obee

Ho provato questo sia in PowerShell che nella shell normale. 1>tee a.txtreindirizzerà stdout su un file denominato teeinvece di chiamare il teecomando. Qualcuno può confermare che questa risposta funziona per loro?
mafu,

@mafu Posso confermare questo.
Cerno,

@mafu La risposta sopra è leggermente errata. Devi usare la pipe "|" anziché ">" nell'esempio principale. Stranamente, l'ordine dell'output STDOUT e STDERR è stato confuso sulla riga di comando in quel caso. L'esempio in basso funziona perfettamente per me però.
Cerno,

Inoltre, il download di sourceforge è stato interrotto per me. Ho trovato un host alternativo qui: wzw.tum.de/public-html/syring/win32/UnxUtilsDist.html (Università di Monaco)
Cerno

9

Se non hai bisogno dell'output in tempo reale (ovvero mentre il programma lo sta scrivendo) potresti aggiungere

type windows-dir.txt

dopo quella linea.


o sulla stessa linea (utile al prompt): dir > windows-dir.txt & type windows-dir.txt. Questo vale anche per i blocchi: ( echo %date% <NL> echo %username% <NL> echo %time% <NL> pause>CON )>test.txt & type test.txt. Tuttavia, se l'output è richiesto in tempo reale, è possibile utilizzare ad es. Una porta windows dello strumento tee per questo ...
mousio

7

La soluzione che ha funzionato per me è stata: dir> a.txt | digitare a.txt .


2
Funziona con un comando con un output basso. Con un comando di output di grandi dimensioni non funziona perché mostra solo il primo buffer. Sta chiedendo un output in tempo reale mentre lo salva in un file di registro.
NetVicious,

Sarebbe problematico se usi >> invece di>
Nime Cloud

6

Sì, c'è un modo per mostrare un singolo comando in uscita sulla console (schermo) e in un file. Usando il tuo esempio, usa ...

@ECHO OFF
FOR /F "tokens=*" %%I IN ('DIR') DO ECHO %%I & ECHO %%I>>windows-dir.txt

Spiegazione dettagliata:

Il FORcomando analizza l'output di un comando o testo in una variabile, a cui è possibile fare riferimento più volte.

Per un comando, ad esempio DIR /B, racchiudere tra virgolette singole come mostrato nell'esempio seguente. Sostituisci il DIR /Btesto con il comando desiderato.

FOR /F "tokens=*" %%I IN ('DIR /B') DO ECHO %%I & ECHO %%I>>FILE.TXT

Per visualizzare il testo, racchiudere il testo tra virgolette doppie come mostrato nell'esempio seguente.

FOR /F "tokens=*" %%I IN ("Find this text on console (screen) and in file") DO ECHO %%I & ECHO %%I>>FILE.TXT

... E con il rivestimento di linea ...

FOR /F "tokens=*" %%I IN ("Find this text on console (screen) and in file") DO (
  ECHO %%I & ECHO %%I>>FILE.TXT
)

Se ci sono momenti in cui si desidera che l'output sia solo sulla console (schermo) e altre volte inviate solo al file e altre volte inviate a entrambi, specificare la clausola "DO" del ciclo FOR utilizzando una variabile, come mostrato di seguito con %TOECHOWHERE%.

@ECHO OFF
FOR %%I IN (TRUE FALSE) DO (
  FOR %%J IN (TRUE FALSE) DO (
    SET TOSCREEN=%%I & SET TOFILE=%%J & CALL :Runit)
)
GOTO :Finish

:Runit
  REM Both TOSCREEN and TOFILE get assigned a trailing space in the FOR loops
  REM above when the FOR loops are evaluating the first item in the list,
  REM "TRUE".  So, the first value of TOSCREEN is "TRUE " (with a trailing
  REM space), the second value is "FALSE" (no trailing or leading space).
  REM Adding the ": =" text after "TOSCREEN" tells the command processor to
  REM remove all spaces from the value in the "TOSCREEN" variable.
  IF "%TOSCREEN: =%"=="TRUE" (
      IF "%TOFILE: =%"=="TRUE" (
          SET TEXT=On screen, and in "FILE.TXT"
          SET TOECHOWHERE="ECHO %%I & ECHO %%I>>FILE.TXT"
        ) ELSE (
          SET TEXT=On screen, not in "FILE.TXT"
          SET TOECHOWHERE="ECHO %%I"
      )
    ) ELSE (
      IF "%TOFILE: =%"=="TRUE" (
          SET TEXT=Not on screen, but in "FILE.TXT"
          SET TOECHOWHERE="ECHO %%I>>FILE.txt"
        ) ELSE (
          SET TEXT=Not on screen, nor in "FILE.TXT"
          SET TOECHOWHERE="ECHO %%I>NUL"
      )
  )
  FOR /F "tokens=*" %%I IN ("%TEXT%") DO %TOECHOWHERE:~1,-1%
GOTO :eof

:Finish
  ECHO Finished [this text to console (screen) only].
  PAUSE

Dovresti usare delims=invece.
scriptmastere02

3
command > file >&1

È più veloce quando non si scrivono i dati sullo schermo poiché non si riempie il buffer di schifezze ma si lascia piuttosto eseguire il processo batch. se stai eseguendo il debug non userei la sintassi> file.
Sviluppatore casuale

@andynormancx yup ha dimenticato di digitare quello invece di taglia e incolla dal CMD.
Sviluppatore casuale

Non sono riuscito a far funzionare la sintassi sotto un prompt dei comandi di Windows e sono andato invece con il comando type.
JamesEggers,

& 2 funziona ma il file non viene creato quando lo collaudo.
JamesEggers,

5
se faccio "dir> file.txt> & 2" file.txt non viene creato. L'output della directory viene ripetuto nella console ma il file non viene creato. Il file viene creato quando "> & 2" non è presente.
JamesEggers,

2

Se si desidera aggiungere anziché sostituire il file di output, è possibile utilizzare

dir 1>> files.txt 2>> err.txt

o

dir 1>> files.txt 2>>&1

2

La mia opzione era questa:

Creare una subroutine che accetta il messaggio e automatizza il processo di invio alla console e al file di registro.

setlocal
set logfile=logfile.log

call :screenandlog "%DATE% %TIME% This message goes to the screen and to the log"    

goto :eof

:screenandlog
set message=%~1
echo %message% & echo %message% >> %logfile%
exit /b

Se aggiungi una variabile al messaggio, assicurati di rimuovere le virgolette al suo interno prima di inviarlo alla subroutine o potrebbe rovinare il tuo batch. Naturalmente questo funziona solo per l'eco.


WOW YES! Mi piace molto questo!! Ho apportato tre modifiche, spero che ti piacciano. 1) Uso setlocal enabledelayedexpansioninvece di solo setlocal 2) Utilizzo l'espansione ritardata per la variabile del file di registro, quindi >> !logfile!anziché >> %logfile%all'interno della subroutine. In questo modo, funziona quando viene chiamato da un blocco di codice (come all'interno di un'istruzione if). 3) Ho rimosso la riga "imposta messaggio" perché non è necessaria la variabile aggiuntiva. Lo abbiamo già inserito, $~1quindi ho echo $~1entrambi i comandi echo.
Nate,

2

Ho creato una semplice console C # in grado di gestire l'output in tempo reale sia sullo schermo cmd che sul registro

class Tee
{
    static int Main(string[] args)
    {
        try
        {
            string logFilePath = Path.GetFullPath(args[0]);

            using (StreamWriter writer = new StreamWriter(logFilePath, true))
            {
                for (int value; (value = Console.In.Read()) != -1;)
                {
                    var word = Char.ConvertFromUtf32(value);
                    Console.Write(word);
                    writer.Write(word);
                }
            }
        }
        catch (Exception)
        {
            return 1;
        }
        return 0;
    }
}

L'uso del file batch è lo stesso di come usi Unix tee

foo | tee xxx.log

Ed ecco il repository che include Tee.exe nel caso in cui non si disponga di uno strumento per compilare https://github.com/iamshiao/Tee



0

La soluzione fornita da "Tomas R" funziona perfettamente per la domanda dell'OP ed è disponibile in modo nativo.

Prova: chkdsk c:> output.txt | digitare output.txt

L'output di questo comando comporta una percentuale di completamento che ottiene l'output in serie sul file, quindi sembrerà un po 'confuso (cioè il testo verrà aggiunto man mano che avanza). Ciò non accade ai bit che vengono inviati a STDOUT (lo schermo). È come sarebbe se si eseguisse lo stesso comando senza reindirizzamento.


-3

Penso che tu voglia qualcosa del genere:

echo Your Msg> YourTxtFile.txt

O se vuoi una nuova linea:

echo Your Msg>> YourTxtFile.txt

Questi comandi sono ottimi per i log.

Nota: a volte ciò potrebbe causare problemi e sostituire l'intero file di testo sul mio computer.

Un'altra nota: se il file non esiste, verrà creato il file.


1
no, OP voleva avere l'output in un file e sullo schermo. Il tuo scrive solo su file. (Ed >è progettato per sovrascrivere il file. Usa >>per aggiungere )
Stephan
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.