Detect redirection and EOF in Standard Handles
Posted: 15 Jan 2012 23:02
At this post I saw this strange example posted by jeb:
Previous code open my eyes to a so obvious concept I didn't realized before: in any Batch program, subroutine or parentheses-enclosed code block, the DOS standard file handles remains open until the program/subroutine/block ends. Remember that every DOS-Windows running program have 5 Standard Handles identified by an integer number this way: 0=STDIN (keyboard CON, redirected by <), 1=STDOUT (screen CON, redirected by >), 2=STDERR (screen CON, redirected by 2>), 3=STDAUX (serial port AUX) and 4=STDPRN (printer PRN).
EDIT: Windows documentation indicate that handles 3-9 are undefined (available), although it seems that CMD.EXE connect handle 3 to CON: device (keyboard for input, screen for output).
I made a small test to confirm that the standard handles behaves as expected:And the result:
With this idea as base, I wrote a very small and simple .COM program that allows to detect if a standard handle has been redirected to a disk file.
Return the type of given handle via ERRORLEVEL this way:
IF %ERRORLEVEL% LSS 128 (
Handle connected to character device: 3=CON (4=NUL in original DOS)
) ELSE (
Handle connected to disk file: +128=disk file, +64=EOF (low part=drive in original DOS)
)
EDIT: If %errorlevel% is zero, the handle is not connected to any file (undefined handle, like handles 3-9 in Windows CMD.EXE).
For example:Another one:This program also provide (at least!) a method to detect EOF in redirected input file:To get TYPEOFHANDLE.COM program, insert this line at beginning of the Batch file:... and this subroutine at end:
P.S. - When both STDIN and STDOUT handles are redirected to disk files, this command: SET /P VAR=%VAR% do a simultaneous output-input operation: the previous value of VAR is sent to STDOUT (with no CR+LF) and a new value of VAR is read from STDIN.
jeb wrote:...Code: Select all
@echo off
setlocal EnableDelayedExpansion
< testfile.txt (
set /p line=
echo set/p-read: !line!
echo --- FINDSTR ---
findstr /n ^^
echo --- MORE ---
more
echo --- FIND ---
find /n /v ""
)
None of the commands close the input stream, even if they are at the end the stream is still open.
FIND and MORE first resets the file position variable and then read the complete file to the EOF, so both can be used to reread the same file multiple times.
jeb
Previous code open my eyes to a so obvious concept I didn't realized before: in any Batch program, subroutine or parentheses-enclosed code block, the DOS standard file handles remains open until the program/subroutine/block ends. Remember that every DOS-Windows running program have 5 Standard Handles identified by an integer number this way: 0=STDIN (keyboard CON, redirected by <), 1=STDOUT (screen CON, redirected by >), 2=STDERR (screen CON, redirected by 2>), 3=STDAUX (serial port AUX) and 4=STDPRN (printer PRN).
EDIT: Windows documentation indicate that handles 3-9 are undefined (available), although it seems that CMD.EXE connect handle 3 to CON: device (keyboard for input, screen for output).
I made a small test to confirm that the standard handles behaves as expected:
The program:thefile.txt wrote:Line one
Line two
Line three
Line four
Line five
Code: Select all
@echo off
setlocal EnableDelayedExpansion
findstr /N ^^ thefile.txt | find /C ":" > lines.tmp
set /P lines=< lines.tmp
rem Copy twice the number of input lines:
set /A lines*=2
< thefile.txt (
for /L %%i in (1,1,%lines%) do (
set /P line=
echo Copy of line %%i: !line!
)
) >> thefile.txt
The new data appended to the end of the file via STDOUT handle is ready to be read when STDIN's File Pointer reaches it, although both handles refer to the same physical file.Result wrote:Line one
Line two
Line three
Line four
Line five
Copy of line 1: Line one
Copy of line 2: Line two
Copy of line 3: Line three
Copy of line 4: Line four
Copy of line 5: Line five
Copy of line 6: Copy of line 1: Line one
Copy of line 7: Copy of line 2: Line two
Copy of line 8: Copy of line 3: Line three
Copy of line 9: Copy of line 4: Line four
Copy of line 10: Copy of line 5: Line five
With this idea as base, I wrote a very small and simple .COM program that allows to detect if a standard handle has been redirected to a disk file.
Code: Select all
TYPEOFHANDLE handle
Return the type of given handle via ERRORLEVEL this way:
IF %ERRORLEVEL% LSS 128 (
Handle connected to character device: 3=CON (4=NUL in original DOS)
) ELSE (
Handle connected to disk file: +128=disk file, +64=EOF (low part=drive in original DOS)
)
EDIT: If %errorlevel% is zero, the handle is not connected to any file (undefined handle, like handles 3-9 in Windows CMD.EXE).
For example:
Code: Select all
TypeOfHandle 0
if %errorlevel% geq 128 (
rem STDIN redirected to disk file
echo This program must be executed in interactive (not predefined-input) way^!
goto :EOF
)
set /P input=Enter input please:
etc...
Code: Select all
TypeOfHandle 1
if %errorlevel% == 3 (
echo Summary of results to be displayed in the screen...
) else (
echo The complete results
echo that will be stored
echo in the redirected disk file...
)
Code: Select all
:nextLine
set line=
set /P line=
echo(%line%
TypeOfHandle 0
set /A eof=%errorlevel% ^& 64
if %eof% == 0 goto nextLine
Code: Select all
if not exist TypeOfHandle.com call :CreateTypeOfHandle
Code: Select all
:CreateTypeOfHandle
setlocal DisableDelayedExpansion
set TypeOfHandle=ëWëOë82Ò2ÿ³‹û2íŠMÿã^>° üó®t7Š]ÿ€û0r/€û9w*€ë02À´DÍ!rÎö€tË€âëĀʀ€â¿°',!´DÍ!"Àu²€Ê@ŠÂ´LÍ!ë«
setlocal EnableDelayedExpansion
echo !TypeOfHandle!> TypeOfHandle.com
exit /B
P.S. - When both STDIN and STDOUT handles are redirected to disk files, this command: SET /P VAR=%VAR% do a simultaneous output-input operation: the previous value of VAR is sent to STDOUT (with no CR+LF) and a new value of VAR is read from STDIN.