Отображение вывода командной строки Windows и перенаправление его в файл - PullRequest
334 голосов
/ 28 апреля 2009

Как я могу запустить приложение командной строки в командной строке Windows и одновременно выводить и перенаправлять вывод в файл?

Если, например, я должен был запустить команду dir > test.txt, это перенаправит вывод в файл с именем test.txt без отображения результатов.

Как можно написать команду для отображения вывода и перенаправить вывод в файл в командной строке Windows, аналогично команде tee в Unix?

Ответы [ 30 ]

8 голосов
/ 16 мая 2014

Если у вас есть Cygwin в вашем пути среды Windows, вы можете использовать:

 dir > a.txt | tail -f a.txt
8 голосов
/ 18 июня 2016

Я хотел бы немного подробнее рассказать о превосходном ответе саксонского Дрюса .

Как уже говорилось, вы можете перенаправить вывод исполняемого файла в текущий каталог следующим образом:

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

Однако, это только регистрирует stdout до test.txt. Он также не регистрирует stderr.

Очевидным решением было бы использовать что-то вроде этого:

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

Однако, это не будет работать для всех something.exe. Некоторые something.exe будут интерпретировать 2>&1 как аргумент и потерпят неудачу. Правильное решение - вместо этого иметь только апострофы вокруг something.exe и его переключатели и аргументы, например:

powershell ".\something.exe --switch1 --switch2 … arg1 arg2 …" 2>&1 | tee test.txt
6 голосов
/ 02 ноября 2011

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

Это поможет перенаправить STDOUT и STDERR

.
4 голосов
/ 02 декабря 2014

Я тоже искал такое же решение, после небольшой попытки мне удалось добиться этого в командной строке. Вот мое решение:

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

Он даже захватывает любую команду PAUSE.

4 голосов
/ 23 января 2015

отправить вывод на консоль, добавить в журнал консоли, удалить вывод из текущей команды

dir  >> usb-create.1 && type usb-create.1 >> usb-create.log | type usb-create.1 && del usb-create.1
3 голосов
/ 02 ноября 2011

Вот пример того, что я использовал, основываясь на одном из других ответов

@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
)
3 голосов
/ 20 мая 2013

Я знаю, что это очень старая тема, но в предыдущих ответах не было полной реализации Tee реального времени, написанной в пакетном режиме. Мое решение ниже - это гибридный скрипт Batch-JScript, который использует секцию JScript просто для получения вывода от конвейерной команды, но обработка данных выполняется в секции Batch. Этот подход имеет то преимущество, что любой программист Batch может модифицировать эту программу в соответствии с конкретными потребностями. Эта программа также корректно обрабатывает вывод команды CLS, созданный другими пакетными файлами, то есть очищает экран при обнаружении вывода команды 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");
3 голосов
/ 05 апреля 2016

Что-то вроде этого должно делать то, что вам нужно?

%DATE%_%TIME% > c:\a.txt & type c:\a.txt
ipconfig >> c:\a.txt & type c:\a.txt
ping localhost >> c:\a.txt & type c:\a.txt
pause
2 голосов
/ 03 декабря 2010
@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

Это создаст файл журнала с текущей датой и временем, и вы сможете использовать строки консоли во время процесса

2 голосов
/ 27 июля 2015

Это вариант предыдущего ответа от MTS, однако он добавляет некоторые функции, которые могут быть полезны для других. Вот метод, который я использовал:

  • В качестве переменной задается команда, которую можно использовать позже в коде для вывода в командное окно и добавления в файл журнала, используя set _Temp_Msg_Cmd=
    • команда сбежала перенаправление с использованием символа моркови ^, чтобы команды не оценивались изначально
  • Временный файл создается с именем файла, аналогичным запускаемому пакетному файлу, и называется %~n0_temp.txt, который использует синтаксис расширения параметра командной строки %~n0 для получения имени пакетного файла.
  • Вывод добавляется в отдельный файл журнала %~n0_log.txt

Вот последовательность команд:

  1. Вывод и сообщения об ошибках отправляются во временный файл ^> %~n0_temp.txt 2^>^&1
  2. В этом случае содержимое временного файла:
    • добавлено в файл журнала ^& type %~n0_temp.txt ^>^> %~n0_log.txt
    • вывод в командное окно ^& type %~n0_temp.txt
  3. Временный файл с сообщением удален ^& del /Q /F %~n0_temp.txt

Вот пример:

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

Таким образом, команда может быть просто добавлена ​​после более поздних команд в командный файл, который выглядит намного чище:

echo test message %_Temp_Msg_Cmd%

Это можно добавить и в конец других команд. Насколько я могу сказать, это будет работать, когда сообщения имеют несколько строк. Например, следующая команда выводит две строки, если появляется сообщение об ошибке:

net use M: /D /Y %_Temp_Msg_Cmd%

...