1

I am looking to build a tail to read log files on windows using only native cmd.

There are various ways to to read a file:

type file.txt
more file.txt

They however do not have a default option to read updates from a file, so does not represent anything like tail.

Gerhard
  • 22,678
  • 7
  • 27
  • 43
  • Would this work for you: https://stackoverflow.com/a/52921862/1417694 – Squashman Jul 24 '20 at 18:01
  • @Squashman. Thanks I created this more as a self QA, however, I did see that solution from I the only difference with my solution does in fact echo empty lines as well, where Dave's does not, as the variable has to be defined... upvoted that one by the way. – Gerhard Jul 24 '20 at 18:13
  • 1
    Yep. I was reminded of that just the other day because I reposted that code as a solution to another question on Dostips just recently. Dave's thread on Dostips really didn't mean for the code to necessarily tail a file. I think he put the `IF DEFINED` into his code to make sure the line wasn't blank. So you could just remove the IF DEFINED and let it echo and do the pathping to slow things down a bit. – Squashman Jul 24 '20 at 18:19
  • @Squashman, true, but I must admit I quite like the way `more` handles the output, come to think of it, it actually just game a another idea, will test and update my answer. – Gerhard Jul 24 '20 at 18:49
  • 1
    Gerhard read this [Dostips thread](https://www.dostips.com/forum/viewtopic.php?t=2961) about a caveat with the `MORE` command. – Squashman Jul 24 '20 at 19:29

1 Answers1

1

With a few little hacks and using more to read the file, skipping what was already read before, we are able to tail the file, "almost" realtime.

@echo off & set cnt=0
if "%~1" == "" echo no file specified, usage: "tail.cmd <filename>"  & goto :eof
if not exist "%~1" echo file "%~1" does not exist & goto :eof
:tail_sub
2>nul (>>"%~1" echo off) && (goto :file) || (goto :tail_sub)
:file
for /f "tokens=1*delims=]" %%i in ('more "%~1" +%cnt% ^| find /v /n ""') do (
    set "line=%%j"
    set /a cnt+=1
    call echo(%%line%%
)
goto :tail_sub

Currently, without adding a timeout to slow down the infinite loop, it consumes around 5.6MB memory, which is very acceptable in my view. This does not yet take care of all special characters, like |<>&, but I will spend some time on this to cater for all scenarios I can think off.

Gerhard
  • 22,678
  • 7
  • 27
  • 43
  • 1
    should be a bit faster and safer with `set cnt=%%i` and `echo(%%j` (and adapting to `delims=[]` of course) – Stephan Jul 24 '20 at 19:08
  • thanks @Stephan, I actually had it like that, I think it will show in the edit history, maybe not `:)` but tried various variations and ended up with this, but I am trying something slightly different now, will update if that does not work to what you mentioned now. – Gerhard Jul 24 '20 at 19:22
  • @Stephan, I remember now, that method did not work, it keep running though a counting loop, I will have a look soon at what exactly happened and try explain. – Gerhard Jul 24 '20 at 19:46