¿Cómo echo y envío la salida de la consola a un archivo en un script bat?

Tengo un script por lotes que ejecuta una tarea y envía el resultado a un archivo de texto. ¿Hay alguna manera de mostrar el resultado en la ventana de la consola también?

Por ejemplo:

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

¿Hay alguna forma de tener el resultado de mostrar dir en la ventana de la consola y ponerlo en el archivo de texto?

Editado bit >> tldr; No, no puedes.

Intento explicar la redirección un poco.

Redirige uno de los diez flujos con > archivo o
No es importante, si la redirección es anterior o posterior al comando, entonces estas dos líneas son casi las mismas.

 dir > file.txt > file.txt dir 

La redirección en este ejemplo es solo un atajo para 1> , esto significa que la secuencia 1 (STDOUT) será redirigida.
Por lo tanto, puede redireccionar cualquier secuencia precediendo el número 2> err.txt y también se puede redirigir varias secuencias en una línea.

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

En este ejemplo, la “salida estándar” irá a files.txt, todos los errores estarán en err.txt y la secuencia 3 entrará en nothing.txt (DIR no usa la secuencia 3).
Stream0 es STDIN
Stream1 es STDOUT
Stream2 es STDERR
Stream3-9 no se utilizan

Pero, ¿qué ocurre si intentas redirigir la misma transmisión varias veces?

 dir > files.txt > two.txt 

“Puede haber solo uno”, ¡y siempre es el último!
Por lo tanto, es igual a dir> two.txt

Ok, hay una posibilidad adicional, redirigir una transmisión a otra transmisión.

 dir 1>files.txt 2>&1 

2> y 1 redirige stream2 a stream1 y 1> files.txt redirige todo a files.txt .
¡El orden es importante aquí!

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

son diferentes. El primero redirige todos (STDOUT y STDERR) a NUL,
pero la segunda línea redirige el STDOUT a NUL y STDERR al STDOUT “vacío”.

Como conclusión, es obvio por qué los ejemplos de Otávio Décio y andynormancx no pueden funcionar.

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

Ambos intentan redirigir stream1 dos veces, pero “There is one only”, y siempre es el último.
Entonces obtienes

 command 1>&1 dir 1>&2 

Y en la primera muestra, el redireccionamiento de stream1 a stream1 no está permitido (y no es muy útil).

Espero eso ayude.

Solo use la versión para Windows del comando tee de UNIX (que se encuentra en http://unxutils.sourceforge.net ) de esta manera:

 mycommand > tee outpu_file.txt 

Si también necesita la salida STDERR, entonces use lo siguiente.
El 2>&1 combina la salida STDERR en STDOUT (la transmisión principal).

 mycommand 2>&1 | tee output_file.txt 

Si no necesita el resultado en tiempo real (es decir, mientras el progtwig lo está escribiendo) puede agregar

 type windows-dir.txt 

después de esa línea.

La solución que funcionó para mí fue: dir> a.txt | escriba a.txt .

Sí, hay una manera de mostrar un solo resultado de comando en la consola (pantalla) y en un archivo. Usando tu ejemplo, usa …

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

Explicación detallada:

El comando FOR analiza el resultado de un comando o texto en una variable, que se puede referenciar varias veces.

Para un comando, como DIR /B , encierre entre comillas simples como se muestra en el ejemplo a continuación. Reemplace el texto DIR /B con su comando deseado.

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

Para mostrar texto, encierre texto entre comillas dobles como se muestra en el ejemplo a continuación.

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

… Y con el ajuste de línea …

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

Si tiene momentos en los que desea la salida solo en la consola (pantalla), y otras veces solo se envía al archivo, y otras veces se envía a ambas, especifique la cláusula “DO” del ciclo FOR utilizando una variable, como se muestra a continuación 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 
 command > file >&1 

Si desea agregar en lugar de reemplazar el archivo de salida, es posible que desee utilizar

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

o

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

Me gusta la respuesta de atn, pero no fue tan trivial para mí descargar como un wintee , que también es de código abierto y solo da la funcionalidad de tee (útil si solo quieres tee y no todo el conjunto de utilidades de Unix). Me enteré de esto desde la respuesta de Davor a la visualización de la salida del símbolo del sistema de Windows y su redireccionamiento a un archivo , donde también se encuentra una referencia a las utilidades de Unix.

Mi opción fue esto:

Cree una subrutina que capte el mensaje y automatice el proceso de envío tanto a la consola como al archivo de 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 

Si agrega una variable al mensaje, asegúrese de eliminar las comillas antes de enviarlo a la subrutina o puede atornillar su lote. Por supuesto, esto solo funciona para hacer eco.

Hice una consola C # simple que puede manejar la salida en tiempo real tanto para la pantalla del cmd como para el 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; } } 

El uso del archivo por lotes es el mismo que el uso de la tee Unix

 foo | tee xxx.log 

Y aquí está el repository que incluye el Tee.exe en caso de que no tenga la herramienta para comstackr https://github.com/iamshiao/Tee

La solución proporcionada por “Tomas R” funciona perfectamente para la pregunta del OP y está disponible de forma nativa.

Pruebe: chkdsk c:> output.txt | tipo output.txt

La salida de este comando implica un porcentaje de finalización que se envía en serie al archivo, por lo que se verá un poco desordenado (es decir, el texto se agregará a medida que avance). Esto no sucede con los bits que se envían a STDOUT (la pantalla). Es lo que sería si solo haces el mismo comando sin redirección.