I am trying to set timestamp data from stdin (to a log file) using a windows batch file

I am collecting data from the API using the wget DOS port to generate data for a log file (which will be analyzed later). The API provides all the information I need, except for the current time (it provides time at the beginning of the data stream, but not after that).

The API typically provides 10 lines of data, and then a line every 20-30 seconds.

I'm trying to make a timestamp for this output and copy it to a log file - I don't mind if the timestamp is on the same line as the rest of the output or the line before.

First, I started with this batch file:

addtimes.bat:

@echo off >nul :start set /p input="": echo %time% echo %input% goto:start 

(called "wget โ€‹โ€‹..... | addtimes.bat> log.log")

However, this led to data loss: the beginning of many lines of data was lost.

I looked over here and realized that I should use a for loop.

addtimes2.bat:

 @echo off cls setlocal EnableDelayedExpansion for /F "tokens=*" %%a in ('more') do ( echo !time! %%a ) ) 

I tried with and without Enabled Delayed Expansion.

It seems I canโ€™t transfer information one line at a time with a different timestamp - all my lines get the same timestamps when I close the data stream.

Typical input data are:

 [1,"219","265",14528,1359031137000,1359031137000] [1,"6594","358",18188,1359031019000,1359031019000] [1,"690","94",15920,1359031534000,1359031534000] [1,"25164","102",2129,1359031457000,1359031457000] [1,"3488","329",2109,1359030868000,1359030868000] [1,"37247","6",11506,1359031223000,1359031223000] 

You may notice that the data has UTC time, but this is not the current time.

+6
source share
2 answers

I do not believe that you can get the result that you need using a pure native party. The reason all your times are the same is because the FOR / F loop does not process the input lines until the entire input stream is buffered (the command to the left of the channel is completed). The FOR / F command waits until all input has been received, and then flushes each line into one crazy rush. If the input stream is large enough, you will get small changes in time, but nothing close to the view when the original command created each line.

Here is a hybrid JScript / script package that does what you want. It works fine as a direct JScript file, but then you need to explicitly use CSCRIPT. A hybrid approach makes the utility more convenient.

Name it addtimes.bat and use it the same way as before.

 @if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment ::************ Batch portion *********** @echo off cscript //E:JScript //nologo "%~f0" exit /b 0 ************* JScript portion **********/ while (!WScript.StdIn.AtEndOfStream) { var ts = new Date() var ms = (ts.getTime() % 1000) WScript.Stdout.WriteLine( ts.getFullYear() + "-" + ((ts.getMonth()<9)?"0":"") + (ts.getMonth()+1) + "-" + ((ts.getDate()<10)?"0":"") + ts.getDate() + " " + ((ts.getHours()<10)?"0":"") + ts.getHours() + ":" + ((ts.getMinutes()<10)?"0":"") + ts.getMinutes() + ":" + ((ts.getSeconds()<10)?"0":"") + ts.getSeconds() + "." + ((ms<10)?"00":((ms<100)?"0":"")) + ms + " - " + WScript.StdIn.ReadLine() ); } 


EDIT

wmz has a very smart and dangerous solution. This solution can be simplified. No need to guess with Autorun.

Warning - as wmz said, the solution below can have very bad consequences if any output line starts with an executable command or program name! I do not recommend using this solution, but I am very interested.

 (echo @prompt $D $T -$S & YourCommandHere )|cmd 2>nul|findstr /rbc:"../../.... ..:..:..\... - " >log.log 

A FINDSTR pipe is added to cut out the CMD header information, the initial PROMPT command, and the unnecessary blank line that the CMD inserts after each โ€œcommandโ€. The FINDSTR regular expression may need to be changed to the specification of the prompt you selected and your locale.

+4
source

Please be careful: this can have many side effects (or it may not work at all, or make your system unstable, etc.) and is not tested. This is more exercise in the party than anything else.

EDIT: See debenham's answer for a refined way to use this idea.

  • set the time request ( prompt $T ) or the date if you prefer ( prompt $D $T ). You will need to do this in Autorun in the registry ( HKEY_CURRENT_USER\software\Microsoft\Command Processor ) so that it is by default. If there is no autorun key, create one (it contains the commands executed when the cmd prompt opens)
  • Run the cmd prompt, then output the output of your command to another cmd.exe and redirect the output of this file:
    more | cmd 2>nul >timestamped.log more | cmd 2>nul >timestamped.log (you would use your command where I used more ). Use more enter:

this message
which was marked as ^ Z

creates the following lines in timestamped.log (after two lines with cmd processor version information):

23: 19: 57,17_this - message
23: 19: 59,95_, which was marked timedamped

This works because cmd will try to write to the log. This fails (and the error message is suppressed / sent to nul), but at the same time echoes with a hint (time / date).

You must be very careful if your journal messages are not quoted (or, more generally, if you are unsure of their format, or they are not created under your direct control) - if your line starts with a word that is a valid command - it will be done!

+3
source

All Articles