0

TL;DR;

In CMD batch file on win - How to append / print a full loop output to both file AND screen simultaneously && continuously ?

Long Version :

I know that this is more of a powershell / bash task, or generally better suited for *nix / piping, but for some reason I need to do that on win (7!) batch / cmd.

I have a somewhat hacked super simple small primitive loop ( on win 7 ) with some network tasks to check (local) DNS listings updates every x seconds, flush local DNS and then check again for propagation. from win, to later be parsed by another script.

@echo off
set "domain=mydomain.TLD"
set "dns_host=dnshost.TLD"
set "NS1=ns1.dnshost.TLD"
set "NS2=ns1.dnshost.TLD"
set "neutralDNS=8.8.8.8"
set "timeout=60"
set "outputfile=myfile.txt"
FOR /L %%A IN (1,1,200) DO (
ECHO ************************************************  
ECHO ********* Checking %domain% On %NS1% //  %NS2%
ECHO ************* Loop Count :: %%A  %Time% 
ipconfig /flushdns
timeout  %timeout% 
ping %domain%
ping %dns_host%
ping %NS1%
ping %NS2%
nslookup %domain% %neutralDNS%
nslookup %dns_host% %NS1% 
nslookup ns1.%dns_host%

REM ... Loop goes on here, commands are not really important
REM host %dns_host%// we are not on *nix !
REM dig  %dns_host% @%neutralDNS% // we are not on *nix !
)

I would like to append the output of the loop to both file and screen, but when I try to append the output with >> myfile.txt like so :

 FOR /L %%A IN (1,1,200) DO (
    ECHO ************* Loop Count :: %%A  %Time% 
   ......
    ) >> %outputfile%

The execution simply fails, and when I try to output to file with > myfile like so :

 FOR /L %%A IN (1,1,200) DO (
    ECHO ************* Loop Count :: %%A  %Time% 
   ......
    ) > %outputfile%

The file will overwrite itself with every iteration.

Another issue is that there is no screen output on both cases except for explicit echo.

Obmerk Kronen
  • 15,619
  • 16
  • 66
  • 105
  • You need to be clear, your question appears to be asking about outputting to both screen and file, yet you have not attempted that task at all. In fact you seem to be having an issue just outputting to file. When you haven't attempted the task, your question becomes an off topic code request, so perhaps you should work out how to correctly output to your file first, then attempt to output also to CONsole later. This may help with the former, `(For /L %%A In (1,1,200) Do (commands))>"%outputfile%"`. – Compo Jun 16 '19 at 10:10
  • @Compo I am sorry, But I do not understand where and how did you come to the conclusion that I did not tried, when in fact I did tried and even wrote so. When it is outputting to file there is not output to screen except explicit echo. – Obmerk Kronen Jun 16 '19 at 10:37
  • I concluded that because your question does not show that you have managed to output to either the console or the file that asking how to output to both is a step too far. That conclusion was based, because I'm not a mind reader, only on the information you provided. It is clear that you haven't attepted to output to both in your provided code or supplementary information. I have read what you posted, which has only attempted and failed to output to a file. Please note that my comment above provided you with the first part of your issue, how to output the full loop to a file, _please try it_! – Compo Jun 16 '19 at 10:54
  • The problem is not the output to file.. the problem is how to output to file while seeing the loop running on screen at the same time .. – Obmerk Kronen Jun 16 '19 at 11:01
  • The problem clearly is outputting it to a file, because your question specifically shows it. There is no `tee` in standard Windows batch scripting, unless you create something which acts in the same way or leverage another language. In order to do that, you would specifically have to tell us which of the commands or their output within the loop require to be sent to the console and/or the file, and whether each of those require STDOUT and STDERR to be output too. – Compo Jun 16 '19 at 11:04
  • 2
    you need a Windows version of `tee` (google it), or a [poor man's solution](https://stackoverflow.com/a/21072977/2152082) – Stephan Jun 16 '19 at 11:06
  • It is very nice of you to define the problem for me, but the output to file is indeed working without a problem. I will say again - my question is how to output to both screen and file at the same time. the script with `>>%outputfile%` outputs to file just fine , and without `>>%outputfile%` it outputs to screen just fine. how to do both is the question. – Obmerk Kronen Jun 16 '19 at 11:10
  • @Stephan - thanks for the answer. Indeed I know `tee` ( and pipes) and it is exactly whats missing. your linked answer might be what I need As soon as I understand how to implement it. Just adding it as-is to the loop will output the content of the script itself one time per loop. – Obmerk Kronen Jun 16 '19 at 11:17
  • put the two `set` commands somewhere at the beginning of the script and instead of `command | tee`, do `command %logg%` – Stephan Jun 16 '19 at 11:22
  • I'll just reiterate what you stated with regards your two methods of outputting to file, **1.** Using `>> %outputfile%` `The execution simply fails` and **2.** with `> %outputfile%`, `The file will overwrite itself with every iteration`. So please do not argue that there `the script with >>%outputfile% outputs to file just fine`. If things have changed, since your original post, then use the [edit facility](https://stackoverflow.com/posts/56616305/edit), to bring your question up to date. – Compo Jun 16 '19 at 12:18
  • @Compo. I have already wrote that in comments to other answer and I will indeed edit the original question when the solution will be found. I invite you to read also the title. No, wait. you know what? you win. You're right. Thank you for defining my problem for me. Very helpful ( and constructive ) comments indeed. (simply fails == fails output on screen ) – Obmerk Kronen Jun 16 '19 at 13:00
  • @Stephan pretty cool solution :) – SNR Jun 16 '19 at 13:12

1 Answers1

1

As per @Stephan comments and the implementation of poor's man solution (or original code) which consists on creating a temporary file and then type the lines written in the temporary file. The code to work as expected can be written as,

.
.
.

set "outputfile=myfile.txt"

::Poor's man solution
set "display=> _ & type _ & type _ >> %outputfile%"

FOR /L %%A IN (1,1,200) DO (
ECHO ************************************************ %display%
ECHO ********* Checking %domain% On %NS1% // %NS2% %display%
ECHO ************* Loop Count :: %%A %Time% %display%

::Simple test
ping 127.0.0.1 %display%

.
.
.

)

del /q /f _

When loop is finished we should del/erase the temporary file.

Long explanation

This piece of code can be subdivided in three steps. First redirects the output with >to _ then type the content of _ and finally appends the content of _ into %outputfile%. Since it goes line by line we are just appending the output of the result of each command.

SNR
  • 712
  • 1
  • 8
  • 22
  • Thanks for the answer , but Setting `echo on` ( inside the loop or outside ) will just output the content of the batch script itself to screen ( with parameters filled ) but not the output of the commands . Also can you explain what is `2>&1` in your answer ? – Obmerk Kronen Jun 16 '19 at 10:47
  • Redirect `stderr` and `stdout` to file. Then, I guess the best bet is to `type` (command) the specific part of the file you are running once you have redirected the output. Does appending work now? – SNR Jun 16 '19 at 10:50
  • I am not sure what you mean by `type` - and yes, the append to file is working ( it was a simple error of a space character in front of the filename ). I also tried to add `TYPE %outputfile%` at the end of the loop - it did not work and got my CLI to stuck and be not-responsive ! :-) – Obmerk Kronen Jun 16 '19 at 10:59
  • Type `type /?` it might help. – SNR Jun 16 '19 at 11:00
  • Ok, I will look into that as soon as I find a way to kill the cli ! :-) – Obmerk Kronen Jun 16 '19 at 11:02
  • Hehe .. Funny enough - No ! Try to run the script with that addition. it was actually funny :-) never saw something like that. `ctrl-c` not work and even task manager fails to kill process. – Obmerk Kronen Jun 16 '19 at 11:32
  • It seems that the correct solutions involves the use of `type` command :). – SNR Jun 16 '19 at 12:15
  • Yep, your edited solution using @Stephan hint works perfect! thanks a lot. a bit strange though that it is needed to put the `%display% at every line and every command. isn't there a work around for that ? taking the whole loop at once ? 1000 thanks again ! – Obmerk Kronen Jun 16 '19 at 14:39
  • I don't think so. My first guess when I saw `echo` wasn't working as we expected was to use `type` to read the log file. Then, thanks to @Stephan we got the correct answer. Actually `%display%` is just the constant part of the whole command. Yes, we are redirecting each by each command here. – SNR Jun 16 '19 at 14:45
  • Ok, thanks a lot again. I just thought there might be a way to take the whole output of the whole loop and do that once at the end. It will not produce true real time display - but code would be cleaner. something like `loop.. ) >>file.txt` that takes all the loop and append to file .. :-) anyhow thanks ! – Obmerk Kronen Jun 16 '19 at 14:47
  • You can try it (writing it at the end). Probably, it will `type` at the end of the whole `loop`. – SNR Jun 16 '19 at 14:53