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.

user3085030
fonte

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.
dbenham
fonte
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
66

se você deseja que os fluxos de saída e de erro sejam redirecionados

dir >> a.txt 2>&1
Kalpesh Soni
fonte
27
+1. Também vale a pena apontar que usar >>irá anexar a a.txt. Em a.txtvez disso, para substituir , use >. stackoverflow.com/q/4458231/1098302
Aaron
Oi, existe alguma maneira de redirecionar a saída no console também?
Sandeep Singh
isso é o que faz
Kalpesh Soni
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.

Anthony
fonte
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.

Magoo
fonte
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
fonte
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 

AquaAlex
fonte
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.

Indra Permana
fonte
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
ilgitano
fonte
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).

jan antonin
fonte
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 .

GioVi
fonte