Redirecionando a saída de dentro do arquivo de lote


110

Estou criando um arquivo em lote com alguns comandos simples para reunir informações de um sistema. O arquivo em lote contém comandos para obter a hora, informações de IP, usuários, etc.

Montei todos os comandos em um arquivo em lote e ele roda, mas gostaria que o arquivo em lote, quando executado, produzisse os resultados em um arquivo de texto (log). Existe um comando que posso adicionar ao lote que faria isso?

Lembre-se de que não quero executar o lote do cmd e, em seguida, redirecionar a saída; Quero redirecionar a saída de dentro do lote, se isso for possível.

Respostas:


161

A maneira simples e ingênua que é lenta porque abre e posiciona o ponteiro do arquivo para o fim do arquivo várias vezes.

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

Uma maneira melhor - mais fácil de escrever e mais rápida porque o arquivo é aberto e posicionado apenas uma vez.

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

Outra maneira boa e rápida que só abre e posiciona o arquivo uma vez

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

:sub
command1
command2
...
commandN

Editar 2017-04-2020

De vez em quando, você pode querer gravar repetidamente em dois ou mais arquivos. Você também pode querer mensagens diferentes na tela. Ainda é possível fazer isso de forma eficiente redirecionando para identificadores indefinidos fora de um bloco ou sub-rotina entre parênteses e, em seguida, usar a &notação para referenciar os arquivos já abertos.

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

Eu escolhi usar as alças 9 e 8 na ordem reversa porque dessa forma é mais provável que evite o redirecionamento permanente potencial devido a uma falha de design de implementação de redirecionamento da Microsoft ao executar vários redirecionamentos no mesmo comando. É altamente improvável, mas mesmo essa abordagem pode expor o bug se você tentar o suficiente. Se você realizar o redirecionamento, terá a garantia de evitar o problema.

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

:sub
etc.

2
Adoro as soluções em que posso configurá-lo para o restante do arquivo
Sam

3
Observe que a solução de chamada muda seu % 0 (para sub , neste caso), que pode ou não ser o que você deseja.
Jannes

1
@Jannes - Verdade, mas você sempre pode obter informações sobre o script de lote em execução se adicionar um modificador. Por exemplo, %~f0sempre fornece o caminho completo para o script em lote, mesmo quando dentro de uma sub-rotina CALLed :.
dbenham

3
@ThariqNugrohotomo ->output.txt 2>&1
dbenham

2
@Moondra - essa é a sintaxe de lote padrão para chamar uma sub-rotina rotulada dentro do mesmo script. Execute cmd /?ou a help cmdpartir da linha de comando do console para documentação. O truque do terceiro método é que o redirecionamento no CALL se aplica a todos os comandos dentro da sub-rotina CALLed.
dbenham


16

Eu sei que esta é uma postagem mais antiga, mas alguém vai topar com ela em uma pesquisa no Google e também parece que algumas perguntas que o OP fez nos comentários não foram abordadas especificamente. Além disso, vá com calma, pois esta é minha primeira resposta postada no SO. :)

Para redirecionar a saída para um arquivo usando um nome de arquivo gerado dinamicamente, minha abordagem go-to (leia-se: rápido e sujo) é a segunda solução oferecida por @dbenham. Então, por exemplo, este:

@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
)

Irá criar um arquivo como o que você vê nesta imagem do arquivo no diretório de destino

Isso conterá esta saída:

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

Lembre-se também de que essa solução depende da localidade, portanto, tome cuidado como / quando usá-la.


Obrigado, isso foi útil. Pergunta rápida: há um motivo pelo qual você está usando .log versus .txt? Isso faz diferença?
Moondra de

1
@Moondra não, não faz. É apenas semântica neste caso. Isso não quer dizer que não existam aplicativos que requeiram / grep com base no tipo de arquivo, portanto, fique atento se / como seus arquivos estão sendo usados.
Anthony,

9
echo some output >"your logfile"

ou

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

deve preencher a conta.

Se você quiser APPENDa saída, use em >>vez de >. >irá iniciar um novo arquivo de log.


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

Acho que essa é a forma mais elegante. Obrigado Wesley!
Kiswanij

5

Há um pequeno programa legal que você pode usar para redirecionar a saída para um arquivo e o console

some_command  ^|  TEE.BAT  [ -a ]  filename 


3
@echo OFF
[your command] >> [Your log file name].txt

Usei o comando acima no meu arquivo em lote e funcionou. No arquivo de log, mostra os resultados do meu comando.


3

Adicione estas duas linhas perto do topo do seu arquivo em lote, todos os stdout e stderr depois serão redirecionados para log.txt:

if not "%1"=="STDOUT_TO_FILE"  %0 STDOUT_TO_FILE %*  >log.txt 2>&1
shift /1

Isso funcionou para mim, obrigado. Alguma consideração especial onde isso pode falhar? (por exemplo, estouro de tamanho de saída)
CCarlos

Oi, obrigado pela sua resposta! existe alguma maneira de redirecioná-lo no console também?
Sandeep Singh

0

Isso pode falhar no caso de caracteres "tóxicos" na entrada. Considerar uma entrada como thisIsAnIn ^^^^ put é uma boa maneira de entender o que está acontecendo. Claro que existe uma regra que determina que uma string de entrada DEVE estar entre aspas duplas, mas tenho a sensação de que essa regra é válida apenas se o significado da entrada for um local em uma partição NTFS (talvez seja uma regra para URLs I não tenho a certeza). Mas não é uma regra para uma string de entrada arbitrária, é claro (é uma "boa prática", mas você não pode contar com ela).


0

Adicionar as seguintes linhas na parte inferior de seu arquivo em lote pegará tudo exatamente como exibido na janela CMD e exportará para um arquivo 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

Basicamente, ele seleciona tudo -> copiar para a área de transferência -> colar no arquivo de texto .

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.