Read stdin stream in a batch file
Solution 1
set /p
doesn't work with pipes, it takes one (randomly) line from the input.
But you can use more
inside of an for-loop.
@echo off
setlocal
for /F "tokens=*" %%a in ('more') do (
echo #%%a
)
But this fails with lines beginning with a semicolon (as the FOR-LOOP-standard of eol is ;
).
And it can't read empty lines.
But with findstr you can solve this too, it prefix each line with the linenumber, so you never get empty lines.
And then the prefix is removed to the first colon.
@echo off
setlocal DisableDelayedExpansion
for /F "tokens=*" %%a in ('findstr /n "^"') do (
set "line=%%a"
setlocal EnableDelayedExpansion
set "line=!line:*:=!"
echo(!line!
endlocal
)
Alternatively, on some environments (like WinRE) that don't include findstr
, an alternative with find.exe
might suffice. find
will accept a null search string ""
, and allows search inversion. This would allow something like this:
@echo off
setlocal DisableDelayedExpansion
for /F "tokens=*" %%a in ('find /v ""') do (
...
Solution 2
The set "line=!line:*:=!
" syntax is:
set requires one parameter that is
a=b
.
If a contains a space or something, you'll have to use the quotation marks around this parameter. Here I don't see any!line:*:=!
For this syntax, you can type 'set /?
' to see the official description on using variables.
!var!
is like%var%
, to get the value. But!var!
means delayed expansion.
line var name
the first : variable modification mark.
**:= **:=
(empty), replace the string in the variable's value matches "*:
"(virtually from the string start to first :
occurence) with (empty), i.e. delete the substring from start to first colon.
Solution 3
FOR /F "tokens=1* delims=]" %%A IN ('FIND /N /V ""') DO (
> CON ECHO.%%B
>> %File% ECHO.%%B
)
Source here: http://www.robvanderwoude.com/unixports.php#TEE
Comments
-
m0tive almost 2 years
Is it possible to use a piped stdin stream inside a batch file?
I want to be able to redirect the output of one command into my batch file
process.bat
list so:C:\>someOtherProgram.exe | process.bat
My first attempt looked like:
echo OFF setlocal :again set /p inputLine="" echo.%inputLine% if not (%inputLine%)==() goto again endlocal :End
When I test it with
type testFile.txt | process.bat
it prints out the first line repeatedly.Is there another way?
-
m0tive almost 13 yearsThis seems to work. I've not seen the
set "line=!line:*:=!"
syntax before. More batch script madness. I've adapted it slightly to use the MSYS tools;sed "s/^\(.*\)$/\"\1\"/"'
instead offindstr /n $
. The body can then be replaced withecho.%%~a
and it can handle none dos line endings (which I have in alot of files). -
dbenham over 11 yearsBetter to use
FINDSTR /N "^"
. That search will correctly return all lines, including unix formatted lines as well as any final line that may not end with a newline. -
wangzq over 11 yearsI think you can use
for /F "tokens=* eol="
to deal with lines beginning with a semicolon. -
jeb over 11 yearsYes it can handle lines with semicolon, but then it fails with quotes, as EOL=" will not empty EOL
-
Ben about 9 yearsThis doesn't fail on lines that begin with a semi-colon either.
-
Thomas W almost 9 yearsBut for me, it failed on lines starting with
]
. -
wizzwizz4 over 6 years@jeb How about
for /F "tokens=* eol=
<EOF>? -
jeb over 6 years@wizzwizz4 That doesn't remove the EOL, but it's possible, see HOW TO: FOR /F Disabling EOF or using a quote as delim. But even then you can't fetch empty lines, therefore I use find or findstr
-
bers over 4 yearsThe 2nd example (
findstr
) is limited in line length. -
bers over 4 yearsThe same is true for the 3rd example (4096 is the limit here), and lines are cut off without warning. So better use the 2nd example, that one at least gives a warning :)
-
jeb over 4 years@bers The third example is incomplete ((it's an edit from Dan). Batch has a hard limit of 8191 characzers for the line length and also for variables.
-
Gerold Broser over 4 years
!line!
doesn't work withDisableDelayedExpansion
, of course. Furthermore, this doesn't print empty lines. -
Limer about 2 yearswhy not
for /F "tokens=1,* eol=: delims=:" %%A in ('findstr.exe /n "^"') do ( echo %%B ...
? - It eliminates theeol
bug/feature (because it's part ofdelims
), doesn't ignore blank lines (%%A
exists even for those thanks tofindstr /n
) and works with CRLF & LF (but not CR). -
jeb about 2 years@Limer It fails for lines beginning with
:
, because they are consumed by thedelims=:
, too. I changed the$
to"^"
for better line end handling, like dbenham commented