Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

input from pipe or file?

3,144 views
Skip to first unread message

Anonymous

unread,
Sep 11, 2011, 6:39:54 PM9/11/11
to
Dear Batchers,

Sorry if this has come up before,
but I was wondering if there is
a way for a batch file to determine
whether input is being sent to it from a file or a pipe?
Or if it's receiving any input at all?

Thanks!
John

foxidrive

unread,
Sep 11, 2011, 8:55:01 PM9/11/11
to
Your question doesn't have a clear answer without us knowing what you are doing in your code.

If you show us your code it may become clearer to us.


If it is not receiveing any input then the variable will be empty...



--
Regards,
Mic

Todd Vargo

unread,
Sep 12, 2011, 1:46:10 AM9/12/11
to
A batch file only accepts input in the form of parameters. Batch files do
not accept or use input from a pipe or a file. Individual commands within a
batch file (but not all) may accept input from a pipe or file but the batch
file itself only accepts input from parameters.

For further assistance, explain what you are trying to accomplish and if you
have some code you need help with, feel free to post it.

I'm_HERE

unread,
Sep 12, 2011, 4:31:12 AM9/12/11
to
maybe this:

------------8<--------- maybe.bat------
@echo off
@echo %CMDCMDLINE%
------------8<------------------------------

c:\> maybe.bat
"D:\WINDOWS\system32\cmd.exe"

c:\> dir | maybe.bat
D:\WINDOWS\system32\cmd.exe /S /D /c" "Copie de alias.bat""

Tom Lavedas

unread,
Sep 12, 2011, 8:45:12 AM9/12/11
to
On Sep 12, 1:46 am, "Todd Vargo" <tlva...@sbcglobal.netz> wrote
>
> Batch files do not accept or use input from a pipe or a file.

Todd, that used to be true under command.com, but was corrected under
cmd.exe. Try it, for example ...

@echo off
for /f "tokens=*" %%I in ('more') do echo.[%%I]

Pipe a DIR listing through it or redirect files into and/or out of
it. It works well (except for those pesky blank lines).
_________________________
Tom Lavedas

Todd Vargo

unread,
Sep 12, 2011, 4:31:18 PM9/12/11
to
The output does not reflect the contents of DIR.

Todd Vargo

unread,
Sep 12, 2011, 5:36:43 PM9/12/11
to
Is the batch actually receiving the piped input or was it the first
executable program called in the batch grabbing it?

Let me try this test...

@echo off
set /p inp=Requesting user input...
echo inp=[%inp%]

Ok, the SET command will grab the first line of text but lets try a batch
that does more than just one instruction.

@echo off
for /f "tokens=*" %%I in ('more') do echo.[%%I]
set /p inp=Requesting user input...
echo Did batch wait for user input? - no
echo inp=[%inp%] - {change not expected}
pause
echo Did batch pause? - no

echo Make sure to pipe in a long DIR output...
echo Can you [Control]+[C] to abort the batch? - no
echo done.

Ok, I concede that it is possible for a batch to receive piped input in a
limited manner, but I would not use the word "corrected" to describe it
being added in cmd.exe. Has anyone, previous to this discussion, documented
piping input into a batch file with these pitfalls noted? Are there other
known features which are broken by piping input into a batch?

Sorry, I can not offer more time to explore right now.

Tom Lavedas

unread,
Sep 13, 2011, 8:35:05 AM9/13/11
to
Your examples seem flawed to me. The first one ...

set /p inp=Requesting user input...

doesn't work because the scope of the redirection is the batch file,
not just the first statement in the file that accepts input. This
behavior seems consistent to me. If you want subsequent statements to
accept input from the keyboard rather than the redirected StdIn, use a
new CON redirection. Again, it seems like a consistent behavior to
me.

The second problem you cite is like unto the first. The PAUSE
statement is tied to the redirected StdIn. It is again redirectable
to the keyboard like this ...

pause < con

As far as the issue with Control-C, I have often find that unreliable
in breaking a batch file and generally resort to Control-Break,
instead.

All together, I think this accomplishes what you seem to say it can't
do ...

@echo off
for /f "tokens=*" %%I in ('more') do echo.[%%I]
set /p inp=Requesting user input... < con
echo Did batch wait for user input? - yes
echo inp=[%inp%] - {changed as expected}
pause < con
echo Did batch pause? - yes

echo Make sure to pipe in a long DIR output...
echo Can you [Control]+[C] to abort the batch? - no
echo Use Control-Break instead.
echo done.

Having said that, I fully accept your 'right' to disagree. I offer
that building a batch procedure to accepted piped and redirected input
is useful, but thankfully, you are free to use it or not, as YOU see
fit.
________________________________
Tom Lavedas

Todd Vargo

unread,
Sep 13, 2011, 5:09:17 PM9/13/11
to
Ok, very good then. I have not used the CON device in quite a long time that
I forgot about redirecting it.

>
> echo Make sure to pipe in a long DIR output...
> echo Can you [Control]+[C] to abort the batch? - no
> echo Use Control-Break instead.
> echo done.

Although I did not state it, Control-Break did not work either (WinXP). Does
it work for you to abort the piped input batch?

>
> Having said that, I fully accept your 'right' to disagree. I offer
> that building a batch procedure to accepted piped and redirected input
> is useful, but thankfully, you are free to use it or not, as YOU see
> fit.

I don't believe I was disagreeing, but thanks for the conversation just the
same Tom.

Tom Lavedas

unread,
Sep 14, 2011, 8:38:30 AM9/14/11
to
On Sep 13, 5:09 pm, "Todd Vargo" <tlva...@sbcglobal.netz> wrote:

> Although I did not state it, Control-Break did not work either (WinXP).
> Does it work for you to abort the piped input batch?

Yes, but I am in Win7. I don't currently have access to XP to test
there.
______________________________
Tom Lavedas

Frank P. Westlake

unread,
Sep 14, 2011, 9:57:35 AM9/14/11
to
"Anonymous"
news:b460a4ff6923fc2f...@remailer.paranoici.org...
> ... I was wondering if there is
> a way for a batch file to determine
> whether input is being sent to it from a file or a pipe?

I think your answer may have been lost in a desire to create solutions.

It is not clear whether you are asking

(A) if the script can know at all if either is being employed, or

(B) if the script can distinguish between device redirection or a
pipe.

(A) Yes, but it seems that without a third party tool you will have to
first read input (with MORE, FINDSTR, ....) to make that determination.
The input can then be stored for later use if at first you only need to
know if there is any input.

(B) As "I'm_HERE" shows, you might be able to use the token
"%CMDCMDLINE%" to determine if the input was a pipe or a redirection,
depending on your configuration. These three tests of "I'm_HERE"'s
script should show the difference on my system:

C:\T>cmdtest
"C:\Windows\System32\cmd.exe" /k"NewConsole.cmd"

C:\T>dir|cmdtest
C:\Windows\system32\cmd.exe /S /D /c" cmdtest"

C:\T>cmdtest<test.txt
"C:\Windows\System32\cmd.exe" /k"NewConsole.cmd"

The first and third show the script I have set to run each time a
console is opened, and the second shows the name of the script on the
command line. So once I know I have input I can check this token
("%CMDCMDLINE%") for my script name as an argument (/c" cmdtest"); if it
is there then I have a pipe, if it is not there I have redirection.

A note to "I'm_HERE":
Please give up a real name that is easier to type!

Frank


Anonymous

unread,
Sep 14, 2011, 5:45:05 PM9/14/11
to
Dear Frank,

Thanks for your reply. My question was inspired by your HEAD and TAIL
efforts posted to this newsgroup a few years ago. I wanted to do something
similar with SLICE.

Which is to say, I wanted SLICE to accept input from a file or a pipe.
And if it did receive data from a pipe and the user specified a file on
the command line as well, SLICE should see that and throw an error. And if
no file is specified and SLICE isn't in a pipe, that should be an error
too. Is this possible?

Lastly, how can a batch file deal with an empty pipe? How can it know
nothing's ever going to come down that pipe? Or, if it HAS received data,
how can it tell that it has reached the end of the data stream?

Thanks to everyone who replied. Your continued patience is gratefully
appreciated as I climb the L-shaped learning curve,

later,
John

jeb

unread,
Sep 15, 2011, 5:32:27 PM9/15/11
to
I see many different questions here:

1. Can a batch file detect if there is input data anyway or from a
pipe or a redirection?
%cmdcmdline% gives a hint, if it contains "cmd.exe /S /D /c" a pipe
can be assumed
But I didn't see a solution to distinguish between redirection and
"nothing".

2. How do you can access redirected or piped input ?

There is a big difference between these two input types.
Both can be easy used with "more" or "findstr", like this it can even
read empty lines
@echo off
for /f "delims=" %%L in ('findstr /n "^"') do (
set "line=%%L"
setlocal EnableDelayedExpansion
set "line=!line:*:=!"
echo(!line!#
endlocal
)

But using set/p or pause makes a big difference!
@echo off
setlocal EnableDelayedExpansion
for /L %%n in (1,1,10) do (
set "Line="
set /p Line=
echo(!Line!#
)

This works nearly perfect with redirection (you didn't need the
delayed toggling technic like in the findstr solution),
it can read also empty lines, but removes trailing TAB's.
And it can't decide when the redirection is at the EOF-mark

With a pipe this fails completly, as a pipe creates two asynchronos
tasks.
Normally the first data creator task echos all his data before the
second consumer task access any of this data.
So set/p fails here, as it doesn't wait or synchronize with the
consumer data.

OJBakker wrote a very good analysis for redirection with using set /p
http://www.dostips.com/forum/viewtopic.php?f=3&t=2160 (How set/p
works)

And there are more curiosities like this
@echo off
findstr /n "^"
echo ----
more

Using this with a redirection shows the same file two times, as the
"more" can reset the file read position.

jeb

Tom Lavedas

unread,
Sep 16, 2011, 10:10:13 AM9/16/11
to
On Sep 15, 5:32 pm, jeb <xi...@gmx.de> wrote:
>
> And there are more curiosities like this
> @echo off
> findstr /n "^"
> echo ----
> more
>
> Using this with a redirection shows the same file two times, as the
> "more" can reset the file read position.
>
> jeb

I couldn't make this work in Win7. It only showed the file once from
the Findstr.

I reviewed the posted link with interest. Too bad it doesn't provide
a way to distinguish between an empty line and EOF.

Concerning the original question, that Frank so gently reminded us of,
I can't figure out how to tell one form of input from another, but if
the OP is willing to fall back on a temporary file, I think this
version of the set/p approach works correctly, regardless of input
method ...

@echo off
%2 more %1>"%temp%.\tmp.txt"
%2 call %0 %1 :: :: < "%temp%.\tmp.txt"
%2 del "%temp%.\tmp.txt"
%2 exit /b 0
setlocal EnableDelayedExpansion
for /f %%C in (
'type "%temp%.\tmp.txt" ^| find /v /c ""'
) do (for /L %%n in (1,1,%%C) do (
set "Line="
set /p Line=%%n#
echo(!Line!#
)
)

I even tested with all three being designated in the same command.
The output can be piped or redirected. I added the line numbering
just for the heck of it.
________________________
Tom Lavedas

Frank P. Westlake

unread,
Sep 17, 2011, 9:17:52 AM9/17/11
to
"Anonymous" news:5f024271d236aa48...@remailer.paranoici.org...

If your remailer permits, let it keep the message header
"References:" so that your articles will be in their
proper place in the tree.

^ Lastly, how can a batch file deal with an empty pipe?
^ How can it know nothing's ever going to come down that
^ pipe? Or, if it HAS received data, how can it tell
^ that it has reached the end of the data stream?

I think you are referring to the case where input is
being taken from the console instead of from a pipe or
redirection. When a program seeks input it is designed
to come from a human; pipes and redirection are the
script's method of overriding that human. The system
terminates piped and redirected input, the human must
still terminate human input. A program should normally
expect that the input device is a human and provide
suitable instruction. The two scripts in this message
demonstrate.

Jeb has shown us that we can now distinguish between
pipes and redirection, at least on my WV-HOBOS SP1.
Here's the basic idea:

:: BEGIN SCRIPT ::::::::::::::::::::::::::::::::::::::::::::::::::::
:: inputdemo.cmd
:: From the desk of Frank P. Westlake, 2011-09-17.
:: Demonstrate how to determine the input method.
:: Based on concepts introduced by "I'm_HERE" and Jeb
:: in alt.msdos.batch.nt.
::
:: From the command line test in these four ways:
:: inputdemo file
:: TYPE file | inputdemo
:: inputdemo
:: inputdemo < file
@Echo OFF
:: BEGIN TEST.
Set "INPUT=STANDARD INPUT"
Set "TempFile=%TEMP%\inputStash"
If EXIST "%TempFile%" ERASE "%TempFile%"
Set "InputFile=%1"
If DEFINED InputFile (
Set "INPUT=COMMANDLINE"
) Else (
Echo %CMDCMDLINE%|FINDSTR "\"/c\" %0">NUL: && (
Set "INPUT=PIPE"
) || (
Echo=Type or paste text, enter [CTRL-Z][ENTER] to terminate.>&3 2>NUL:
FINDSTR "^" > "%TempFile%"
For %%f in ("%TempFile%") Do (
If "%%~zf" NEQ "0" (
Echo=Enter [CTRL-Z][ENTER] to terminate.>&3 2>NUL:
For /F %%t in ('MORE ^| FINDSTR "^"') Do Set "INPUT=REDIRECTION"
)
)
)
)
:: END TEST.
:: DO SOMETHING WITH THE RESULT.
Set INPUT
If "%INPUT%"=="COMMANDLINE" (
TYPE "%InputFile%"
) Else If "%INPUT%"=="PIPE" (
MORE
) Else If "%INPUT%"=="STANDARD INPUT" (
TYPE "%TempFile%"
) Else If "%INPUT%"=="REDIRECTION" (
TYPE "%TempFile%"
) Else (
Echo=Uh oh!!
)
If EXIST "%TempFile%" ERASE "%TempFile%"
:: END SCRIPT ::::::::::::::::::::::::::::::::::::::::::::::::::::::

I did some experimenting with your SLICE idea and put
together a script with some different ideas. Then Jeb
posted his "!variable:*:=!" technique which is a much
better idea then what I came up with, so I added his
idea to my script and provided the option to use one
or the other. I haven't fully tested either method so
this will be useful to someone wishing to do so.

My script follows. Things to note are:

- filespecs with wildcards (i.e. text*.*);
- multiple filespecs (i.e. *.txt *.xml);
- recursion into subdirectories (FOR /R);
- calculation of string offset to skip line numbers;
- calls itself to show its own documentation.
- the use of file stream 3 (>&3);
- the use of lead-free text and recyclable bits.

I have columns set to 132 in this message so I have not
indented nor otherwise mutilated the lines.

Frank

:: BEGIN SCRIPT ::::::::::::::::::::::::::::::::::::::::::::::::::::
:: PrintLines.cmd
:: From the desk of Frank P. Westlake, 2011-09-17.
@Echo OFF
If "%1" EQU "/?" (%0 7 33 %~f0 & Goto :EOF)
Goto :main to avoid documentation.

USAGE
Format 1:
PrintLines [/s] start end filespec [filespec [filespec [...]]]
Format 2 (redirected files):
PrintLines [[start] end] < FILE
Format 3 (piped files):
COMMAND | PrintLines [[start] end]

Options
/? Show documentation.
/s Check for the file[s] in subdirectories.
start May be negative if end is positive.
The start will become end+start.
If start is absent it will become 1.
end May be negative if start is positive.
The end will become 0xFFFFFFFF.
If end is absent it will become 0xFFFFFFFF.

Format 1:
- Wildcards are accepted for multiple files.
- The filename is printed to file stream 3, which may be
redirected to NUL:. For example:
PrintLines /s 1 10 *.txt *.xml 3>NUL:
- If 'end' is 0 then only the file names are printed, none of the file is
printed.
Format 2 and 3:
- 'end' is required only if 'start' is specified. No '/s' and no wildcards.

:main
SetLocal EnableExtensions
Set "FPW=" & Set "JEB=REM"
::Set "FPW=REM" & Set "JEB="
If /I "%1"=="/S" (SHIFT & Set "Subdirs=/R") Else (Set "Subdirs=")
Set "start=%1" & Set "end=%2"
If NOT DEFINED start (Set "start=1")
If NOT DEFINED end (Set "end=%1" & Set "start=1")
If NOT DEFINED end (Set "end=0xFFFFFFFF")
If %end% LSS 0 (Set "end=0xFFFFFFFF"
) Else If %start% LSS 0 (Set /A "start=end+start")
:Work Cycle through each filespec
Set "file=%~3"
SHIFT
If DEFINED file (
For %Subdirs% %%f in (%file%) Do (
If EXIST "%%~f" (
Echo===== %%f ====>&3
If %end% GTR 0 Call :PrintLines %start% %end% "%%f"
)
)
) Else (REM Pipe or redirection.
Call :PrintLines %start% %end%
)
If NOT "%3"=="" Goto :Work
Goto :EOF

::::::::::::::::::::::::::
:PrintLines start end file
SetLocal EnableExtensions DisableDelayedExpansion
%JEB% Set /A "L=0"
%FPW% Set /A "L=0, N=10, O=2"
For /F "delims=" %%T in ('FindStr /n "^" %3') Do (
%JEB% Set /A "L+=1"
%FPW% Set /A "L+=1, t=N, N*=1+!(N-L)*9, O=O+!!(N-t)"
Set "print=%%T"
SetLocal EnableDelayedExpansion
%JEB% If !L! GEQ %1 (If !L! LEQ %2 (Echo=!print:*:=!))
%FPW% If !L! GEQ %1 (If !L! LEQ %2 (For /L %%O in (!O! 1 !O!) Do Echo=!print:~%%O!))
EndLocal
)
:: END SCRIPT ::::::::::::::::::::::::::::::::::::::::::::::::::::::



Todd Vargo

unread,
Sep 17, 2011, 6:56:20 PM9/17/11
to
Have you tried this?

@echo off
echo %CMDCMDLINE% | find /i "\cmd.exe /S /D /c" >nul
if %errorlevel% equ 0 (
if not "%~3% equ "" (
Echo ERROR: input filespec not valid with piped input.
goto :eof [or display syntax]
)
)
::...

jeb

unread,
Sep 18, 2011, 1:38:16 PM9/18/11
to

jeb

unread,
Sep 18, 2011, 5:45:37 PM9/18/11
to
Hmm, reading my last post I missed my text ...
So I try it again.

Frank P. Westlake wrote:
> ...
Echo=!print:*:=!
> ...

Using echo= is not safe against any content, as it fails (like nearly
all echoX variations) with one of three possible contents.
<empty>
/?
\..\myBatch.bat -- the batch file myBatch.bat should exists in the
current directory

Currently I only discovered that echo( can handle all three cases.

set "line="
echo(!line!
set "line=/?"
echo(!line!
echo echo Hello World > myBatch.bat
set "line=\..\myBatch.bat"
echo(!line!

But the rest of Frank's code looks fine and should work as expected.

jeb

Frank P. Westlake

unread,
Sep 21, 2011, 9:42:51 AM9/21/11
to
:: inputDemo2.cmd
:: From the desk of Frank P. Westlake, 2011-09-21
::
:: Determines if there is redirected or piped input waiting and identifies
:: which it is. This test conforms to the precedence of REDIRECTION over PIPE.
::
:: This test is not reliable because if file handle 3 is mishandled by any
:: process in this console group then the handle can become lost or confused.
::
:: This test is not reliable because there are other command line
:: configurations which will pass the test as a PIPE but which have no pipe.
::
:: Unfortunately this test prints a blank line in the console window
:: if input is not REDIRECTION.
@Echo OFF
SetLocal EnableExtensions

:: This file catches the error report if input is REDIRECTION. It will be deleted.
Set "TempFile=%TEMP%\inputTest"

:: INPUT either remains undefined or it is defined with either "REDIRECTION" or "PIPE".
Set "INPUT="

:: BEGIN TEST.
:: Print something redirected to the console window. This redirection fails if the
:: input stream has been redirected from a file; an error report is sent to "%TempFile%".
:: ERRORLEVEL does not receive the value of this error so the report is necessary.
:: This redirection does not fail if it is done in FOR's execution chamber so it must be
:: done here.
Echo(>&3 2>"%TempFile%"

For %%f in ("%TempFile%") Do (
ERASE "%TempFile%"
REM If file size is not 0 there was a redirection error so the input type is REDIRECTION.
If "%%~zf" NEQ "0" (
Set "INPUT=REDIRECTION"
) Else (
REM "I'm_HERE"'s pipe test. Determine if a PIPE is indicated.
Echo %CMDCMDLINE%|FINDSTR "\"/c\" %0">NUL: && Set "INPUT=PIPE"
)
)
:: Finished. Show the result.
If DEFINED INPUT (
Echo Input type is %INPUT%
REM Show the input.
MORE
) Else (
Echo No PIPE and no REDIRECTION.
)



Liviu

unread,
Feb 6, 2012, 1:26:07 AM2/6/12
to
"Frank P. Westlake" <frank.w...@gmail.com> wrote...
>
> :: inputDemo2.cmd

Interesting, thanks to all who contributed. Not directly related, but
would anyone know of a way to detect whether the _output_ is piped
or redirected?

> :: This test is not reliable because if file handle 3 is mishandled
> by any process in this console group then the handle can become
> lost or confused.

I'd also add "hung" to the list. On my xp.sp3 at least the following
requires either a ^Z-Enter or ^C-^C to end.

| C:\>inputDemo2 | more
|
| Input type is PIPE
|
| ^CThe process tried to write to a nonexistent pipe.
| ^C^C^C
| C:\>

Is there any formal documentation about handle 3 usage in batch files?

Liviu


Aacini

unread,
Mar 26, 2012, 10:20:18 PM3/26/12
to
You may detect if STDIN, STDOUT or any standard handle is redirected
to a disk file or pipe with the small .COM program I presented here:

http://www.dostips.com/forum/viewtopic.php?f=3&t=2800
0 new messages