The synchronization mechanism implemented in the Batch file below works on line-by-line basis. If you want to pass through the pipe the multi-line output of a command, it must be splitted in individual lines that must be processed by the semaphore system. Also, a conventional value is needed in order to detect the real End Of input Stream.
Code: Select all
@echo off
setlocal EnableDelayedExpansion
rem Synchronization of concurrent input/output pipe operations via a semaphore system
rem Example of TEE feature for a particular program
rem Antonio Perez Ayala
rem Define auxiliary variable for nested CALLs of this Batch file
set CALL="%~F0"
rem Nested Batch file call dispatcher
if "%~1" equ ":Source" goto Source
if "%~1" equ ":Tee" goto Tee
echo The text between the lines will be "TEE'd" into TeeOutput.txt file
echo ------------------------------------------------------------------
rem Create the semaphore-signal file
echo X > Flag.out
del Flag.in 2> NUL
rem Execute the Source of text and pipe it into the TEE subroutine
del TeeOutput.txt 2> NUL
%CALL% :Source | %CALL% :Tee TeeOutput.txt
echo ------------------------------------------------------------------
echo End of TEE example
goto :EOF
:Source
setlocal DisableDelayedExpansion
call :SendData Today is %date% @ %time%
call :SendData Listing of "DIR *.BAT" command:
call :SendData
for /F "tokens=1* delims=:" %%a in ('dir *.bat ^| findstr /N "^"') do (
call :SendData "%%b"
)
call :SendData
call :SendData End of data duplicated by TEE
rem Send the special data that indicate "End Of piped File"
call :SendData :EOF
exit /B
rem Each data sent is followed by "data available" signal
rem and then waits for "data read" acknowledgement
:SendData data
echo(%*
rem Set "data available" signal
ren Flag.out Flag.in
:WaitDataAcknow
if not exist Flag.out goto WaitDataAcknow
exit /B
:Tee file
rem Wait for "data available" signal
if not exist Flag.in goto Tee
rem Read the input line
set line=
set /P line=
rem Set "data read" acknowledgement
ren Flag.in Flag.out
rem Check for special "End Of piped File" data
if "!line!" equ ":EOF" exit /B
rem Duplicate input line in Stdout and into the parameter file
set "enclosingQuotes=!line:~0,1!!line:~-1!"
if !enclosingQuotes! equ "" set "line=!line:~1,-1!"
echo(!line!
echo(!line!>> %2
goto Tee
Previous mechanism may also be used in other piped scenarios, not just in Tee command.
Although it is possible to implement a similar mechanism via a FOR /F command that get input lines from a process and duplicate they in Stdout and a tee file, this mechanism is synchronous, that is, the output will appear in the screen until the process that generate it ends. On the other hand, the mechanism shown above is simultaneous (asynchronous) so screen output will appear as soon as the output is generated.
Antonio