Redirigir la salida desde el archivo por lotes

110

Estoy creando un archivo por lotes con algunos comandos simples para recopilar información de un sistema. El archivo por lotes contiene comandos para obtener la hora, información de IP, usuarios, etc.

Reuní todos los comandos en un archivo por lotes y se ejecuta, pero me gustaría que el archivo por lotes, cuando se ejecute, genere los resultados en un archivo de texto (registro). ¿Hay algún comando que pueda agregar al lote que lo haría?

Tenga en cuenta que no quiero ejecutar el lote desde cmd y luego redirigir la salida; Quiero redirigir la salida desde el interior del lote, si es posible.

user3085030
fuente

Respuestas:

161

La forma sencilla e ingenua que es lenta porque abre y coloca el puntero del archivo al final del archivo varias veces.

@echo off
command1 >output.txt
command2 >>output.txt
...
commandN >>output.txt

Una forma mejor: más fácil de escribir y más rápida porque el archivo se abre y se coloca solo una vez.

@echo off
>output.txt (
  command1
  command2
  ...
  commandN
)

Otra forma buena y rápida que solo abre y coloca el archivo una vez

@echo off
call :sub >output.txt
exit /b

:sub
command1
command2
...
commandN

Editar 2020-04-17

De vez en cuando, es posible que desee escribir repetidamente en dos o más archivos. También es posible que desee diferentes mensajes en la pantalla. Todavía es posible hacer esto de manera eficiente redirigiendo a identificadores no definidos fuera de un bloque o subrutina entre paréntesis, y luego usar la &notación para hacer referencia a los archivos ya abiertos.

call :sub 9>File1.txt 8>File2.txt
exit /b

:sub
echo Screen message 1
>&9 File 1 message 1
>&8 File 2 message 1
echo Screen message 2
>&9 File 1 message 2
>&8 File 2 message 2
exit /b

Elegí usar los identificadores 9 y 8 en orden inverso porque de esa manera es más probable que se evite una posible redirección permanente debido a un defecto de diseño de implementación de redirección de Microsoft al realizar múltiples redirecciones en el mismo comando. Es muy poco probable, pero incluso ese enfoque podría exponer el error si se esfuerza lo suficiente. Si organizas la redirección, tienes la garantía de evitar el problema.

3>File1.txt ( 4>File2.txt call :sub)
exit /b

:sub
etc.
dbenham
fuente
2
Me encantan las soluciones en las que puedo configurarlas para el resto del archivo
Sam
3
Tenga en cuenta que la solución de llamada cambia su % 0 (a sub en este caso) que puede ser o no lo que desea.
Jannes
1
@Jannes: es cierto, pero siempre puede obtener información sobre el script por lotes en ejecución si agrega un modificador. Por ejemplo, %~f0siempre proporciona la ruta completa al script por lotes, incluso cuando está dentro de una subrutina CALLed :.
dbenham
3
@ThariqNugrohotomo ->output.txt 2>&1
dbenham
2
@Moondra: esa es la sintaxis estándar por lotes para llamar a una subrutina etiquetada dentro del mismo script. Ejecute cmd /?o help cmddesde la línea de comandos de la consola para obtener documentación. El truco del tercer método es que la redirección en CALL se aplica a todos los comandos dentro de la subrutina CALLed.
dbenham
66

si desea redirigir las transmisiones de salida y error

dir >> a.txt 2>&1
Kalpesh Soni
fuente
27
+1. También vale la pena señalar que el uso se >>agregará a a.txt. Para sobrescribir en su a.txtlugar, use >. stackoverflow.com/q/4458231/1098302
Aaron
Hola, ¿hay alguna forma de redirigir la salida en la consola también?
Sandeep Singh
eso es lo que hace
Kalpesh Soni
16

Sé que esta es una publicación más antigua, pero alguien se encontrará con ella en una búsqueda de Google y también parece que algunas preguntas que hizo el OP en los comentarios no se abordaron específicamente. Además, tenga cuidado conmigo, ya que esta es mi primera respuesta publicada en SO. :)

Para redirigir la salida a un archivo utilizando un nombre de archivo generado dinámicamente, mi enfoque de referencia (leer: rápido y sucio) es la segunda solución ofrecida por @dbenham. Entonces, por ejemplo, esto:

@echo off
> filename_prefix-%DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.log (
echo Your Name Here
echo Beginning Date/Time: %DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.log
REM do some stuff here
echo Your Name Here
echo Ending Date/Time: %DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.log
)

Creará un archivo como el que ves en esta captura de pantalla del archivo en el directorio de destino

Eso contendrá esta salida:

Your Name Here
Beginning Date/Time: 2016-09-16_141048.log
Your Name Here
Ending Date/Time: 2016-09-16_141048.log

También tenga en cuenta que esta solución depende de la configuración regional, así que tenga cuidado de cómo y cuándo la usa.

Antonio
fuente
Gracias esto fue útil. Pregunta rápida: ¿hay alguna razón por la que está utilizando .log frente a .txt? Eso hace una diferencia?
Moondra
1
@Moondra no, no lo hace. Es solo semántica en este caso. Eso no quiere decir que no haya aplicaciones que requieran / grep según el tipo de archivo, así que tenga en cuenta si se están utilizando sus archivos y cómo.
Anthony
9
echo some output >"your logfile"

o

(
 echo some output
 echo more output
)>"Your logfile"

debe llenar la factura.

Si desea APPENDla salida, use en >>lugar de >. >iniciará un nuevo archivo de registro.

Magoo
fuente
9
@echo off
>output.txt (
echo Checking your system infor, Please wating...

systeminfo | findstr /c:"Host Name" 
systeminfo | findstr /c:"Domain"

ipconfig /all | find "Physical Address" 

ipconfig | find "IPv4" 
ipconfig | find "Default Gateway"

)

@pause
saif
fuente
Creo que esta es la forma más elegante. ¡Gracias Wesley!
Kiswanij
5

Hay un pequeño programa genial que puede usar para redirigir la salida a un archivo y la consola

some_command  ^|  TEE.BAT  [ -a ]  filename 

AquaAlex
fuente
4

Agregue estas dos líneas cerca de la parte superior de su archivo por lotes, todos los stdout y stderr posteriores serán redirigidos a log.txt:

if not "%1"=="STDOUT_TO_FILE"  %0 STDOUT_TO_FILE %*  >log.txt 2>&1
shift /1
ilgitano
fuente
Esto funcionó para mí, gracias. ¿Alguna consideración especial donde esto pueda fallar? (por ejemplo, desbordamiento del tamaño de salida)
CCarlos
¡Hola, gracias por su respuesta! ¿Hay alguna forma de redirigirlo también en la consola?
Sandeep Singh
3
@echo OFF
[your command] >> [Your log file name].txt

Usé el comando anterior en mi archivo por lotes y funciona. En el archivo de registro, muestra los resultados de mi comando.

Indra Permana
fuente
0

Esto puede fallar en el caso de caracteres "tóxicos" en la entrada. Teniendo en cuenta una entrada como esta, IsAnIn ^^^^ poner es una buena manera de entender lo que está sucediendo. Seguro que hay una regla de que una cadena de entrada DEBE estar entre comillas dobles, pero tengo la sensación de que esta regla es una regla válida solo si el significado de la entrada es una ubicación en una partición NTFS (tal vez sea una regla para las URL I no estoy seguro). Pero no es una regla para una cadena de entrada arbitraria, por supuesto (es "una buena práctica" pero no puede contar con ella).

Jan Antonin
fuente
0

Agregar las siguientes líneas en la parte inferior de su archivo por lotes tomará todo tal como se muestra dentro de la ventana CMD y lo exportará a un archivo de texto:

powershell -c "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys('^a')
powershell -c "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys('^c')
powershell Get-Clipboard > MyLog.txt

Básicamente realiza una selección de todo -> copiar al portapapeles -> pegar en el archivo de texto .

GioVi
fuente