Page 1 of 2

Piped input and output to a batch file

Posted: 21 Dec 2011 12:05
by b264740
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

Re: Piped input and output to a batch file

Posted: 23 Dec 2011 14:06
by Squashman
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%

Re: Piped input and output to a batch file

Posted: 23 Dec 2011 14:12
by orange_batch
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"

Re: Piped input and output to a batch file

Posted: 23 Dec 2011 14:35
by Squashman
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.

Re: Piped input and output to a batch file

Posted: 23 Dec 2011 15:07
by orange_batch
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 ...

Re: Piped input and output to a batch file

Posted: 24 Dec 2011 21:32
by dbenham
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

Re: Piped input and output to a batch file

Posted: 24 Dec 2011 22:12
by Squashman
That is pretty cool

Re: Piped input and output to a batch file

Posted: 03 Jan 2012 22:12
by Aacini
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.

Re: Piped input and output to a batch file

Posted: 03 Jan 2012 22:42
by dbenham
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

Re: Piped input and output to a batch file

Posted: 03 Jan 2012 22:59
by Aacini
Yes you are right, but SET /P is the only way that a Batch file may behave like a "filter command": anycommand | aBatchFile.

Re: Piped input and output to a batch file

Posted: 03 Jan 2012 23:15
by dbenham
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

Re: Piped input and output to a batch file

Posted: 05 Jan 2012 11:46
by Aacini
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.

Re: Piped input and output to a batch file

Posted: 20 Jan 2012 13:19
by Squashman
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

Re: Piped input and output to a batch file

Posted: 20 Jan 2012 13:38
by Squashman
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

Re: Piped input and output to a batch file

Posted: 20 Jan 2012 13:53
by aGerman
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