Piped input and output to a batch file

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
b264740
Posts: 1
Joined: 21 Dec 2011 11:48

Piped input and output to a batch file

#1 Post by b264740 » 21 Dec 2011 12:05

Folks,

I wrote a simple batch file to take a file and add a prefix and a suffix to every line in the file. Example: "append pre suf file.ext"

:: append.bat
@echo off
SETLOCAL
set prefix=%~1
set suffix=%~2
set f=%~3
(for /f "tokens=1,* delims=:" %%a in (%f%) do (
(echo.%prefix% "%%a" %suffix%)
)) > temp.txt
rem move /y "temp.txt" "%f%"
EXIT /b

I would like to modify this to act on piped output from another command, add a prefix and a suffix to every line, and output it to the console or pipe to another command. For example: "dir /b > append pre suf" or "dir /b > append pre suf |findstr ..."

How do I do this? Thanks for your suggestions.

Cheers!
-Jason

Squashman
Expert
Posts: 4486
Joined: 23 Dec 2011 13:59

Re: Piped input and output to a batch file

#2 Post by Squashman » 23 Dec 2011 14:06

You are not going to be able to do that without some type of stream editor like SED. They do make ports of it for Win32.

But your examples shows that you want to do this from the output of the DIR command which is easy enough with a FOR LOOP.

Code: Select all

@echo off
SETLOCAL
set prefix=%~1
set suffix=%~2
FOR /F "tokens=*" %%I in ('dir /b /a-d') do echo %prefix% %%I %suffix%

orange_batch
Expert
Posts: 442
Joined: 01 Aug 2010 17:13
Location: Canadian Pacific
Contact:

Re: Piped input and output to a batch file

#3 Post by orange_batch » 23 Dec 2011 14:12

Squashman, that is incorrect...

Jason, working with the output of any command always involves for /f "..." %%a in ('...') do ....

Code: Select all

for /f "delims=" %%a in ('dir /b') do call "append.bat" prefix suffix "%%a"
Last edited by orange_batch on 23 Dec 2011 15:07, edited 1 time in total.

Squashman
Expert
Posts: 4486
Joined: 23 Dec 2011 13:59

Re: Piped input and output to a batch file

#4 Post by Squashman » 23 Dec 2011 14:35

Not understanding how you feel my response was incorrect.
You are not going to be able to use a PIPE to get the desired result he wants unless he would use something like SED or AWK. You would have to use a FOR Loop which is what I provided.

orange_batch
Expert
Posts: 442
Joined: 01 Aug 2010 17:13
Location: Canadian Pacific
Contact:

Re: Piped input and output to a batch file

#5 Post by orange_batch » 23 Dec 2011 15:07

Sorry, you're right about piping specifically, but your code echoes the file names with the prefix and suffix (not modifying the contents). What I mean is, it's possible to do what he asked using batch.

Jason, your code is a little wonky so I'll post a complete solution. This will overwrite your input file. :!:

As a separate batch (append.bat):

Code: Select all

@echo off
for /f "tokens=1* delims=:" %%a in ('type "%~3"^&type nul^>"%~3"') do echo(%~1 "%%a" %~2>>"%~3"
exit/b

Use with:

Code: Select all

for /f "delims=" %%a in ('dir /b') do call "append.bat" prefix suffix "%%a"

As a subroutine:

Code: Select all

@echo off

for /f "delims=" %%a in ('dir /b') do call :append prefix suffix "%%a"

pause
exit

:append
for /f "tokens=1* delims=:" %%a in ('type "%~3"^&type nul^>"%~3"') do echo(%~1 "%%a" %~2>>"%~3"
exit/b

This version will not overwrite your input file:

Code: Select all

@echo off
type nul>"temp.txt"
for /f "usebackq tokens=1* delims=:" %%a in ("%~3") do echo(%~1 "%%a" %~2>>"temp.txt"
exit/b

Now to find a specific line...

Code: Select all

type "temp.txt"|findstr ...

And of course, to do something if the search query is successful would be...

Code: Select all

for /f "delims=" %%a in ('type "temp.txt"^|findstr ...') do ...

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Piped input and output to a batch file

#6 Post by dbenham » 24 Dec 2011 21:32

A batch file can process lines piped into it. I derived this solution from a jeb post on StackOverflow http://stackoverflow.com/a/6980605/1012053
Edit: bug fix - added missing quote

Code: Select all

@echo off
setlocal
set "prefix=%~1"
set "suffix=%~2"
for /f "delims=" %%A in ('findstr /n $') do (
  set "ln="
  set "ln=%%A"
  setlocal enableDelayedExpansion
  if defined ln set "ln=!ln:*:=!"
  echo(!prefix! "!ln!" !suffix!
  endlocal
)


Dave Benham
Last edited by dbenham on 04 Jan 2012 23:26, edited 1 time in total.

Squashman
Expert
Posts: 4486
Joined: 23 Dec 2011 13:59

Re: Piped input and output to a batch file

#7 Post by Squashman » 24 Dec 2011 22:12

That is pretty cool

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Piped input and output to a batch file

#8 Post by Aacini » 03 Jan 2012 22:12

The Batch file below take the prefix and suffix from parameters 1 and 2. If the %3 parameter is given, then it is the name of the input file to process; otherwise the piped input is processed. Anyway, the output is always sent to the standard output (the screen) that is the way that a "filter program" must work.

Code: Select all

@echo off
setlocal
set "prefix=%~1"
set "suffix=%~2"
if not "%3" == "" (
    call :ProcessLines < "%3"
) else (
    call :ProcessLines
)
goto :EOF

:ProcessLines
set line=:EOF
set /P line=
if "%line%" == ":EOF" exit /b
echo %prefix% %line% %suffix%
goto ProcessLines

Previous program ends at the first empty line. Although this point may be fixed when processing a file, there is no way for SET /P command to differentiate an empty line from the end of file when processing the piped input.

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Piped input and output to a batch file

#9 Post by dbenham » 03 Jan 2012 22:42

I don't think SET /P is a good option in this case. The filter program should not terminate upon the first empty line.

Dave Benham

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Piped input and output to a batch file

#10 Post by Aacini » 03 Jan 2012 22:59

Yes you are right, but SET /P is the only way that a Batch file may behave like a "filter command": anycommand | aBatchFile.

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Piped input and output to a batch file

#11 Post by dbenham » 03 Jan 2012 23:15

How does my posted code not work as a filter program? It is easily modified to take the 3rd argument as the optional input file

Code: Select all

@echo off
setlocal
set "prefix=%~1"
set "suffix=%~2"
for /f "delims=" %%A in ('findstr /n $ %3') do (
  set "ln="
  set "ln=%%A"
  setlocal enableDelayedExpansion
  if defined ln set "ln=!ln:*:=!"
  echo(!prefix! "!ln!" !suffix!
  endlocal
)


Dave Benham

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Piped input and output to a batch file

#12 Post by Aacini » 05 Jan 2012 11:46

Excuse me, perhaps I didn't expressed it correctly. SET /P is the only way a Batch file have to get piped input if it use built-in (cmd.exe internal) Batch commands only. If an external executable file is used, then anything is possible, right?

We used to use FINDSTR command for several purposes although it was originally designed to find strings in files. For example, we use FINDSTR to process blank lines in FOR command (inserting a line number that must be removed later) or to get piped input, like in this case.

I wrote a very small and fast program that just read bytes from stdin and sent they to stdout, so I called it PIPE. Additionally it insert a space in empty lines, so the process of this topic may be achieved in a simpler and faster way this way:

Code: Select all

@echo off
setlocal EnableDelayedExpansion
set "prefix=%~1"
set "suffix=%~2"
set inputFile=
if not "%~3" == "" set inputFile=^< "%~3"
for /F "usebackq delims=" %%a in (`pipe ^%inputFile%`) do (
    echo(%prefix% %%a %suffix%
)
My PIPE.COM program is only 69 bytes in size, so it is a very good replacement of FINDSTR to be used in these cases. If you are worried about where to get my program from, here it is; just copy the 69 bytes below to a file named PIPE.COM and it is ready to run:

ë2´)€ì!Í!ŠÐŠà€Ä!€ü.u.€þ+u)R²A€ê!´#€ì!Í!Z´#€ì!Í!Šò€Æ!´,€ì!Í!"ÀuôLÍ!ëã

You may first create a file called PIPE.TXT and then do a REN PIPE.TXT PIPE.COM. If someone is worried about the blank space inserted in empty lines, then PIPE program may be easily modified to insert a colon in every line, the same was as FINDSTR. I wrote this program just to prove my point: anything is possible in a Batch file if we use external programs.

Squashman
Expert
Posts: 4486
Joined: 23 Dec 2011 13:59

Re: Piped input and output to a batch file

#13 Post by Squashman » 20 Jan 2012 13:19

Aacini,
I gave this a try. Just trying to append the actual file name with some spaces padded to the end of every record.
Didn't seem to do anything. It just hung with an error message: Cannot load VDM IPX/SPX support
Using XP Pro 32bit

Code: Select all

@echo off
if not exist pipe.com call :CreatePipe
setlocal EnableDelayedExpansion
set "suffix1=%~n1                   ."
set suffix=%suffix1:~0,20%
set inputFile=^< "%~1"
for /F "usebackq delims=" %%a in (`pipe ^%inputFile%`) do (
    echo(%%a %suffix%>>appended.txt
)
del pipe.com
exit /B

:CreatePipe
setlocal DisableDelayedExpansion
set pipe=ë2´)€ì!Í!ŠÐŠà€Ä!€ü.u.€þ+u)R²A€ê!´#€ì!Í!Z´#€ì!Í!Šò€Æ!´,€ì!Í!"ÀuôLÍ!ëã
setlocal EnableDelayedExpansion
echo !pipe!>pipe.com
exit /B

Squashman
Expert
Posts: 4486
Joined: 23 Dec 2011 13:59

Re: Piped input and output to a batch file

#14 Post by Squashman » 20 Jan 2012 13:38

Well it eventually did output a file. It took a couple of minutes which I thought was kind of long for such a small file. The Input file was only 6MB but it only output a file 2,962,200 bytes. It stopped midstream in the middle of line. The very end of the output was this ^C FILENAME

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Piped input and output to a batch file

#15 Post by aGerman » 20 Jan 2012 13:53

Also doesn't work for me. Not sure, but the forum software would probably change or remove some not printable characters. But I guess you cannot ECHO the characters because of the different character encoding and the appended Cr Lf.
I don't get your error message, but have a look at
http://stackoverflow.com/questions/7327 ... ly-program

Regards
aGerman

Post Reply