non-buffering FOR /F alternative
Posted: 18 Sep 2019 10:34
I developed a little C tool to observe a folder for changes. It is permanently running and writes a line for every event. (Maybe I publish this utility later on if someone finds it useful).
If I try to process the lines in a FOR /F loop it won't work because FOR /F buffers the outputted lines until the utility terminates. Of course the tool is not intended to terminate because it shall continue waiting for the next event. I already figured out how to work around this limitation but still I'm not happy with it.
That's what I have so far:
The code consists of three parts which all process the same output of the three lines
The first part displays nothing until you press Enter. Then it outputs all three lines at once. This is the unwanted behavior I try to work around.
The second part solves the problem partially. I pipe the output to another cmd process containing an infinite loop, and within the body of this loop I read the lines using SET /P. This technique is well-known for reading files. Fun fact: It displays "hello" and then waits for the Enter input. "world" and "stop" are never displayed. Something ate them
In the third part I inserted a delay of one second after each line. This works. And my tests using the C tool indicate that a few milliseconds would be sufficient already. But this is ugly.
Does anyone out there know of a better workaround?
Steffen
If I try to process the lines in a FOR /F loop it won't work because FOR /F buffers the outputted lines until the utility terminates. Of course the tool is not intended to terminate because it shall continue waiting for the next event. I already figured out how to work around this limitation but still I'm not happy with it.
That's what I have so far:
Code: Select all
@echo off &setlocal
for /f "delims=" %%i in ('cmd /c "echo hello&echo world&set /p =stop"') do echo %%i
pause
cls
cmd /c "echo hello&echo world&set /p =stop" | (cmd /von /q /d /c ^"for /l %%# in (^) do set "rec="^&set /p "rec="^&(if not defined rec exit^)^&^
echo !rec!^
")
pause
cls
cmd /c "echo hello&>nul timeout 1&echo world&>nul timeout 1&set /p =stop" | (cmd /von /q /d /c ^"for /l %%# in (^) do set "rec="^&set /p "rec="^&(if not defined rec exit^)^&^
echo !rec!^
")
pause
Because of the SET /P statement that displays "stop", the cmd process doesn't terminate unless you press Enter.hello
world
stop
The first part displays nothing until you press Enter. Then it outputs all three lines at once. This is the unwanted behavior I try to work around.
The second part solves the problem partially. I pipe the output to another cmd process containing an infinite loop, and within the body of this loop I read the lines using SET /P. This technique is well-known for reading files. Fun fact: It displays "hello" and then waits for the Enter input. "world" and "stop" are never displayed. Something ate them
In the third part I inserted a delay of one second after each line. This works. And my tests using the C tool indicate that a few milliseconds would be sufficient already. But this is ugly.
Does anyone out there know of a better workaround?
Steffen