Como faço para ecoar e enviar saída do console para um arquivo em um script de morcego?

Eu tenho um script em lotes que executa uma tarefa e envia a saída para um arquivo de texto. Existe uma maneira de ter a saída mostrada na janela do console também?

Por exemplo:

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

Existe uma maneira de ter a saída de exibição dir na janela do console, bem como colocá-lo no arquivo de texto?

Bit editado >> tldr; Não, você não pode.

Eu tento explicar o redirecionamento um pouco.

Você redireciona um dos dez streams com > arquivo ou
Não é importante se o redirecionamento for antes ou depois do comando, portanto, essas duas linhas são quase iguais.

 dir > file.txt > file.txt dir 

O redirecionamento neste exemplo é apenas um atalho para 1> , isso significa que o stream 1 (STDOUT) será redirecionado.
Assim, você pode redirect qualquer stream com prefixando o número como 2> err.txt e também é permitido redirect vários streams em uma linha.

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

Neste exemplo, a “saída padrão” irá para o arquivo.txt, todos os erros estarão no err.txt e o stream3 irá para o arquivo nothing.txt (o DIR não usa o stream 3).
Stream0 é STDIN
Stream1 é STDOUT
Stream2 é STDERR
Stream3-9 não são usados

Mas o que acontece se você tentar redirect o mesmo stream várias vezes?

 dir > files.txt > two.txt 

“Só pode haver um”, e é sempre o último!
Então é igual a dir> two.txt

Ok, há uma possibilidade extra, redirecionando um stream para outro stream.

 dir 1>files.txt 2>&1 

2> & 1 redireciona stream2 para stream1 e 1> files.txt redireciona todos para files.txt .
A ordem é importante aqui!

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

são diferentes. O primeiro redireciona todos (STDOUT e STDERR) para NUL,
mas a segunda linha redireciona o STDOUT para NUL e STDERR para o STDOUT “vazio”.

Como uma conclusão, é óbvio porque os exemplos de Otávio Décio e andynormancx não podem funcionar.

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

Ambos tentam redirect stream1 duas vezes, mas “pode ​​haver apenas um”, e é sempre o último.
Então você começa

 command 1>&1 dir 1>&2 

E no primeiro exemplo, o redirecionamento de stream1 para stream1 não é permitido (e não é muito útil).

Espero que ajude.

Basta usar a versão do Windows do comando UNIX tee (encontrado em http://unxutils.sourceforge.net ) desta forma:

 mycommand > tee outpu_file.txt 

Se você também precisar da saída STDERR, use o seguinte.
O 2>&1 combina a saída STDERR em STDOUT (o stream principal).

 mycommand 2>&1 | tee output_file.txt 

Se você não precisa da saída em tempo real (ou seja, como o programa está escrevendo) você pode adicionar

 type windows-dir.txt 

depois dessa linha.

A solução que funcionou para mim foi: dir> a.txt | escreva a.txt .

Sim, existe uma maneira de mostrar uma única saída de comando no console (canvas) e em um arquivo. Usando o seu exemplo, use …

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

Explicação detalhada:

O comando FOR analisa a saída de um comando ou texto em uma variável, que pode ser referenciada várias vezes.

Para um comando, como DIR /B , inclua aspas simples, conforme mostrado no exemplo abaixo. Substitua o texto DIR /B pelo comando desejado.

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

Para exibir texto, coloque o texto entre aspas duplas, conforme mostrado no exemplo abaixo.

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

… E com quebra de linha …

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

Se você tiver momentos em que deseja a saída apenas no console (canvas), e outras vezes enviadas apenas para o arquivo, e outras vezes enviadas para ambos, especifique a cláusula “DO” do loop FOR usando uma variável, como mostrado abaixo com %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 

Se você deseja append em vez de replace o arquivo de saída, você pode querer usar

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

ou

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

Eu gosto da resposta da atn, mas não foi tão trivial para mim baixar como wintee , que também é open source e só dá a funcionalidade tee (útil se você quer apenas tee e não todo o conjunto de utilitários unix). Eu aprendi sobre isso a partir da resposta da davor a Exibindo a saída do prompt de comando do Windows e redirecionando-a para um arquivo , onde você também encontra referência aos utilitários unix.

Minha opção foi esta:

Crie uma sub-rotina que receba a mensagem e automatize o processo de enviá-la para o console e o arquivo de log.

 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 você adicionar uma variável à mensagem, lembre-se de remover as aspas antes de enviá-la para a sub-rotina ou pode estragar seu lote. Claro que isso só funciona para ecoar.

Eu fiz um simples console C # que pode manipular a saída em tempo real para a canvas cmd e log

 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; } } 

O uso do arquivo em lote é o mesmo de como você usa o UNIX tee

 foo | tee xxx.log 

E aqui está o repository que inclui o Tee.exe caso você não tenha ferramentas para compilar https://github.com/iamshiao/Tee

A solução fornecida por “Tomas R” funciona perfeita para a pergunta do OP e está disponível nativamente.

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

A saída desse comando envolve uma porcentagem de conclusão que obtém serialmente a saída para o arquivo, portanto ele parecerá um pouco confuso (isto é, o texto será anexado à medida que progride). Isso não acontece com os bits que são enviados para STDOUT (a canvas). É como seria se você fizesse o mesmo comando sem redirecionamento.