[comp.unix.shell] How to pipe stderr to a command in Bourne or Korn shell

pim@cti-software.nl (Pim Zandbergen) (10/08/90)

How can one redirect stderr to a command while leaving stdout unaffected ?
-- 
Pim Zandbergen                          domain : pim@cti-software.nl
CTI Software BV                         uucp   : uunet!mcsun!hp4nl!ctisbv!pim
Laan Copes van Cattenburch 70           phone  : +31 70 3542302
2585 GD The Hague, The Netherlands      fax    : +31 70 3512837

coleman@sunny.DAB.GE.COM (Richard Coleman) (10/09/90)

-- 
In article <1990Oct8.165133.17187@cti-software.nl>, pim@cti-software.nl (Pim Zandbergen) writes:
|> 
|> How can one redirect stderr to a command while leaving stdout unaffected ?


For csh and bash try       (command > temp1) >& temp2
For sh                      command 2> temp

somebody else will have to handle ksh.

     Richard Coleman
     G.E. Simulation & Control Systems
     coleman@sunny.dab.ge.com

jik@athena.mit.edu (Jonathan I. Kamens) (10/09/90)

In article <6133@ge-dab.GE.COM>, coleman@sunny.DAB.GE.COM (Richard Coleman) writes:
|> In article <1990Oct8.165133.17187@cti-software.nl>, pim@cti-software.nl (Pim Zandbergen) writes:
|> |> How can one redirect stderr to a command while leaving stdout unaffected ?
|> For csh and bash try       (command > temp1) >& temp2
|> For sh                      command 2> temp

  The original poster asked how to redirect to a *command*.  You've shown how
to redirect to a *file*.

  In csh, one possible way to do it (when working at a tty) would be:

    (program > /dev/tty) |& command

A similar approach will work in sh (and probably ksh), although there's
probably some better way to do it with various hideous file descriptor
reassignments (I don't use the bourne shell a lot, so I don't qualify to
invent hideous file descriptor reassignments :-):

    (program > /dev/tty) 2>&1 | command

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8495			      Home: 617-782-0710

pfalstad@flower.Princeton.EDU (Paul John Falstad) (10/09/90)

In article <1990Oct8.204053.15797@athena.mit.edu> jik@athena.mit.edu (Jonathan I. Kamens) writes:
>|> |> How can one redirect stderr to a command while leaving stdout unaffected ?
>A similar approach will work in sh (and probably ksh), although there's
>probably some better way to do it with various hideous file descriptor
>reassignments (I don't use the bourne shell a lot, so I don't qualify to
>invent hideous file descriptor reassignments :-):
>
>    (program > /dev/tty) 2>&1 | command

They're not that hideous!

In bash, sh, and (I'm fairly sure) ksh, you can do this and avoid the
subshell:

program 2>&1 >/dev/tty | command

--
     Are you nervy?  Irritable?  Depressed?  Tired of life?  Keep it up!

cpcahil@virtech.uucp (Conor P. Cahill) (10/09/90)

In article <1990Oct8.165133.17187@cti-software.nl> pim@cti-software.nl (Pim Zandbergen) writes:
>
>How can one redirect stderr to a command while leaving stdout unaffected ?

Assuming you are asking this because you are using the c-shell (that doesn't
support 2>) I will point you toward the comp.unix.questions FAQ posting 
(just posted in the last week) question number 16.


-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.,
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

bob@wyse.wyse.com (Bob McGowen x4312 dept208) (10/09/90)

In article <6133@ge-dab.GE.COM> coleman@sunny.DAB.GE.COM (Richard Coleman) writes:
>
>-- 
>In article <1990Oct8.165133.17187@cti-software.nl>, pim@cti-software.nl (Pim Zandbergen) writes:
>|> 
>|> How can one redirect stderr to a command while leaving stdout unaffected ?
		^^^^^^^^	^^^^^^^^^^^^
>
>
>For csh and bash try       (command > temp1) >& temp2
>For sh                      command 2> temp
>
>somebody else will have to handle ksh.
>

The question was how to redirect to a command, not a file.  You might think
that something like 2| would work, but it doesn't (at least in sh, I have
no ksh to try it on).

I have tried several permutations of re-ordering file descriptors and trying
to use new ones with the _exec- builtin but have had no success yet.

Bob McGowan  (standard disclaimer, these are my own ...)
Product Support, Wyse Technology, San Jose, CA
..!uunet!wyse!bob
bob@wyse.com

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (10/09/90)

In article <1990Oct8.204053.15797@athena.mit.edu> jik@athena.mit.edu (Jonathan I. Kamens) writes:
>   In csh, one possible way to do it (when working at a tty) would be:

But who said there's a tty around? What if Pim wanted to pipe his output
through yet another command?

> A similar approach will work in sh (and probably ksh), although there's
> probably some better way to do it with various hideous file descriptor
> reassignments (I don't use the bourne shell a lot, so I don't qualify to
> invent hideous file descriptor reassignments :-):

I use the bourne shell a lot, so I guess I qualify. It isn't too
hideous, though, if you write it clearly:

  ( exec 5>&1; exec 1>&2; exec 2>&5; foo ) | err-processor

Even you :-) should be able to recognize the swap idiom there. Start
from basic constructs like this and soon you'll be piping stdout and
stderr through separate commands. Someday you may even learn to use
multitee... [grin]

---Dan

henk@atcmp.nl (Henk M. Keller) (10/09/90)

In article <1990Oct8.165133.17187@cti-software.nl>, pim@cti-software.nl (Pim Zandbergen) writes:
> 
> How can one redirect stderr to a command while leaving stdout unaffected ?

The real solution in sh and ksh is to exchange stdout and stderr:

	command_1 3>&1 1>&2 2>&3 3>&- | command_2

Well, some comments may be needed :-)
   (a)	3>&1	File descriptor 3 now is an 'alias' for 1 (original stdout)
   (b)	1>&2	File descr. 1 now is an 'alias' for 2 (original stderr)
   (c)	2>&3	File descr. 2 now is an 'alias' for 3 which still is an alias
		for the original stdout
   (d)	3>&-	File descr. 3 is closed as it is no longer needed

Net effect:
	File descriptor 1 (stdout) is connected to the original stderr (b)
	File descriptor 2 (stderr) is connected to the original stdout (c)

For C writers amongst you:
	3>&1 will probably be implemented as
		close(3);	/* To ensure 3 is free */
		fcntl(1, F_DUPFD, 3);	/* Returns lowest possible   */
					/* 'dup'ed file descr. >= 3  */


  /-------------------------------------------------------+
 /  Henk Keller                         AT Computing bv   |
|   Teleph.: +31 80 566880              P.O. Box 1428     |
|   Fax:     +31 80 555887              6501 BK  Nijmegen |
|   Email:   henk@atcmp.nl              The Netherlands   |
|            mcsun!hp4nl!kunivv1!atcmpe!henk              |
|                                                         |
|                    -- do not fold --                    |
+---------------------------------------------------------+

rick@tetrauk.UUCP (Rick Jones) (10/09/90)

In article <3207@idunno.Princeton.EDU> pfalstad@flower.Princeton.EDU (Paul John Falstad) writes:
>In article <1990Oct8.204053.15797@athena.mit.edu> jik@athena.mit.edu (Jonathan I. Kamens) writes:
>>|> |> How can one redirect stderr to a command while leaving stdout unaffected ?
>
>In bash, sh, and (I'm fairly sure) ksh, you can do this and avoid the
>subshell:
>
>program 2>&1 >/dev/tty | command

In sh, file descriptor re-directions are evaluated left to right, so you can
even swap stdout & stderr with a little care & avoid /dev/tty if you want:

program 3>&2 2>&1 >&3 | command

I think this should work in ksh, but doesn't seem to in my version - a buglet?
I can't speak for bash as I don't use it.
-- 
Rick Jones			The definition of atomic:
Tetra Ltd.				from the Greek meaning "indivisible"
Maidenhead, Berks, UK		So what is:
rick@tetrauk.uucp			an atomic explosion?

maart@cs.vu.nl (Maarten Litmaath) (10/10/90)

In article <668@atcmpe.atcmp.nl>,
	henk@atcmp.nl (Henk M. Keller) writes:
)In article <1990Oct8.165133.17187@cti-software.nl>,
)	pim@cti-software.nl (Pim Zandbergen) writes:
)> 
)> How can one redirect stderr to a command while leaving stdout unaffected ?
)
)The real solution in sh and ksh is to exchange stdout and stderr:
)
)	command_1 3>&1 1>&2 2>&3 3>&- | command_2

But that still does _not_ answer Pim's question!
He said: `... while leaving stdout _unaffected_' (emphasis added).
In Henk's example stdout is dup(2)ed to stderr.

So:
	exec 3>&1
	command_1 2>&1 1>&3 3>&- | command_2 3>&-
	exec 3>&-

Or:
	3>&1 (command_1 2>&1 1>&3 3>&- | command_2 3>&-)

	# yes Virginia, that's correct

Don't forget to close the extra descriptor, or you'll get screwed one day.
--
            "the C shell is flakier than a snowstorm."  (Guy Harris)

das@lanai.cs.ucla.edu (David Smallberg) (10/10/90)

In article <5069:Oct903:10:1390@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>In article <1990Oct8.204053.15797@athena.mit.edu> jik@athena.mit.edu (Jonathan I. Kamens) writes:
>> A similar approach will work in sh (and probably ksh), although there's
>> probably some better way to do it with various hideous file descriptor
>> reassignments.
>...
>  ( exec 5>&1; exec 1>&2; exec 2>&5; foo ) | err-processor

Unnecessary subshell creation.  This works under sh and ksh:
	{ pgm1 2>&1 1>&3 | pgm2 ;} 3>&1
Explanation:
     Suppose stdout originally goes to <stdout> (whether that be a file, the
 terminal, or whatever).
     Outside the { }, we open file descriptor 3 to also go to <stdout>.
     pgm2's stdout is unaffected, so it will go to <stdout>.
     The "|" at first causes pgm1's stdout to go into the pipe.
     The "2>&1" causes pgm1's stderr to also go into the pipe.
     The "1>&3" causes pgm1's stdout to no longer go into the pipe, but into
	file descriptor 3, which goes to <stdout>.
Result:
     pgm1's stderr goes into the pipe.
     pgm1's stdout and pgm2's stdout go to the original stdout destination.
     pgm2's stderr goes to the original stderr destination.
Now only pgm1's stderr
	goes into the pipe.
--

-- David Smallberg, das@cs.ucla.edu, ...!{uunet,ucbvax,rutgers}!cs.ucla.edu!das

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (10/10/90)

In article <668@atcmpe.atcmp.nl> henk@atcmp.nl (Henk M. Keller) writes:
> 	3>&1 will probably be implemented as
> 		close(3);	/* To ensure 3 is free */
> 		fcntl(1, F_DUPFD, 3);	/* Returns lowest possible   */
> 					/* 'dup'ed file descr. >= 3  */

Or dup2(1,3).

---Dan

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (10/10/90)

In article <39936@shemp.CS.UCLA.EDU> das@lanai.cs.ucla.edu (David Smallberg) writes:
> In article <5069:Oct903:10:1390@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> >  ( exec 5>&1; exec 1>&2; exec 2>&5; foo ) | err-processor
> Unnecessary subshell creation.

[snif] I feel insulted. No, it does *not* create an extra shell. Perhaps
you should test these things before you post.

This is a good point to remember: certain builtins, such as exec,
correspond directly to system calls between fork() and exec(), and
current shells understand this perfectly.

There's also nothing wrong with using () instead of {} at the beginning
of a pipe; the shell internally surrounds each component of the pipe
with parentheses and then removes redundant levels. (Well, sort of, but
you get the idea.) In fact, {} wastes time, as it requires a semicolon
at the end---something that whoever maintains your script might later
forget.

---Dan

tif@doorstop.austin.ibm.com (Paul Chamberlain) (10/10/90)

In article <3002@wyse.wyse.com> bob@wyse.UUCP (Bob McGowen x4312 dept208) writes:
>In article <1990Oct8.165133.17187@cti-software.nl>, pim@cti-software.nl writes:
>> How can one redirect stderr to a command while leaving stdout unaffected ?
>The question was how to redirect to a command, not a file.  You might think
>that something like 2| would work, but it doesn't (at least in sh, I have
>no ksh to try it on).
>
>I have tried several permutations of re-ordering file descriptors and trying
>to use new ones with the _exec- builtin but have had no success yet.

Just thought I'd take a stab at it.  There may be a better way.
I use Korn Shell.

$ echo now is the time > xx
$ rm -f zz
$ ( cat zz xx 2>&1 1>&3 | od -c ) 3>&1
now is the time
0000000   c   a   t   :       c   a   n   n   o   t       o   p   e   n
0000020       z   z  \n
0000024

Paul Chamberlain | I do NOT represent IBM.     tif@doorstop, sc30661 at ausvm6
512/838-7008     | ...!cs.utexas.edu!ibmaus!auschs!doorstop.austin.ibm.com!tif

das@lanai.cs.ucla.edu (David Smallberg) (10/10/90)

Dan Bernstein writes:
>In article <39936@shemp.CS.UCLA.EDU> das@lanai.cs.ucla.edu (David Smallberg) writes:
>> In article <5069:Oct903:10:1390@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>> >  ( exec 5>&1; exec 1>&2; exec 2>&5; foo ) | err-processor
>> Unnecessary subshell creation.
>
>[snif] I feel insulted. No, it does *not* create an extra shell. Perhaps
>you should test these things before you post.

My apologies.  It's been a while since I've done this kind of stuff under sh,
but I remember that at one time (could be many years ago) there really was an
extra process creation.  As recently as a few months ago, I reported a
situation in which ksh88d could be clever enough to do an exec without a fork,
but wasn't -- I haven't checked yet to see if ksh88e "fixes" it.  So I guess
I trust the shells to do the clever thing less often than they deserve to be
trusted.

>This is a good point to remember: certain builtins, such as exec,
>correspond directly to system calls between fork() and exec(), and
>current shells understand this perfectly.

That's certainly true for builtins.  But as I noted above, even current shells
don't always "understand" some constructs perfectly.  (By "understand", I mean
understand to the point where a fairly obvious unnecessary fork can be
eliminated.)
--

-- David Smallberg, das@cs.ucla.edu, ...!{uunet,ucbvax,rutgers}!cs.ucla.edu!das

les@chinet.chi.il.us (Leslie Mikesell) (10/11/90)

In article <5069:Oct903:10:1390@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:

>But who said there's a tty around? What if Pim wanted to pipe his output
>through yet another command?
>
>  ( exec 5>&1; exec 1>&2; exec 2>&5; foo ) | err-processor
>
>Even you :-) should be able to recognize the swap idiom there. Start
>from basic constructs like this and soon you'll be piping stdout and
>stderr through separate commands. Someday you may even learn to use
>multitee... [grin]

Or FIFO's  (which might even be available on his machine...)

/etc/mknod /tmp/fifo$$ p
err-processor < /tmp/fifo$$ &
command 2>/tmp/fifo$$ | output_processor
rm /tmp/fifo$$

Straightforward enough, and err-processor would not even be required to have
a common parent with the rest of the programs if they have some way
of determining the name to use.

Les Mikesell
  les@chinet.chi.il.us

emanuele@overlf.UUCP (Mark A. Emanuele) (10/14/90)

In article <1990Oct8.165133.17187@cti-software.nl>, pim@cti-software.nl (Pim Zandbergen) writes:
> 
> How can one redirect stderr to a command while leaving stdout unaffected ?

I'm not 100% sure but logically this should work.

command1 2>tempfile &
tail -f tempfile | command2

the only problem I think would be that the tail -f would never end.


another solution:
again I'm not sure but here goes:

command1 2|command2



I have not tried either of these .  let me know if they work.

-- 
Mark A. Emanuele
V.P. Engineering  Overleaf, Inc.
500 Route 10 Ledgewood, NJ 07852-9639         attmail!overlf!emanuele
(201) 927-3785 Voice   (201) 927-5781 fax     emanuele@overlf.UUCP