tee like program to pipe to another program?

Tom Christiansen tchrist at convex.COM
Fri Jun 7 01:01:09 AEST 1991


(Put followups wherever you want -- I just didn't want them to 
land in alt.sources unless they were also source.)

>From the keyboard of dkeisen at leland.Stanford.EDU (Dave Eisen):
:In article <1991Jun6.093939.9346 at dartvax.dartmouth.edu> pete at othello.dartmouth.edu (Pete Schmitt) writes:
:>Is there a tee like program that will pipe down to another program?
:>
:
:Sure. It's called "tee".
:
:Something like:
:
:program1 | tee /dev/tty | program2
:
:should do what you want.

I suspect that this is not want the original poster wanted.  While its
true that it does work in this case, it's not going to work if you want
to "tee off" to a list of processes.

Here's a program that's a supersets of the original tee, so I think
you can just put it in your own bin and call it tee; I did..  

Instead of just file specs, you can give pipe specs like this "|program".
So for the simple suggestion above, the usage would be

    program1 | tee "|program2"

which isn't particularly interesting.  This is:

    program1 | tee "|program2" "|program3" "|program4"

It still understands -a for append and -i for ignoring interrupts
(which I've never used), as well as a new -u for "unbuffered" output,
especially useful with pipes.  You can also mix your appends and
overwrites by specifying ">>file" for appending.  "file" is the same as
">file", unless the -a flag is on, in which case it's ">>file".  
You can always use ">file" or ">>file" to override the default.
For example, not using any defaults:

$ prog1 | tee -u ">file1" "|prog2" ">>file2" "|prog3 | prog4" ">file3" ">>file4"

prog1 runs into tee, which duplicates its output to several different
places.  first, a copy goes to stdout (redirect into /dev/null if you
don't want this.) file1 and file3 get overwritten, file2 and file4 get
appended to, and prog2 and prog3 get run.  oh, and prog3 runs into prog4.

Program follows; not bad for ~30 lines of code, eh? :-)

--tom

#!/usr/bin/perl
#
# tee clone that groks process tees (should work even with old perls)
# Tom Christiansen <tchrist at convex.com>
# 6 June 91

while ($ARGV[0] =~ /^-(.+)/ && (shift, ($_ = $1), 1)) {
    next if /^$/;
    s/i// && (++$ignore_ints, redo); 
    s/a// && (++$append,      redo);
    s/u// && (++$unbuffer,    redo);
    die "usage tee [-aiu] [filenames] ...\n";
} 
if ($ignore_ints) { 
    for $sig ('INT', 'TERM', 'HUP', 'QUIT') { $SIG{$sig} = 'IGNORE'; } 
}
$mode = $append ? '>>' : '>';
$fh = 'FH000';
%fh = ('STDOUT', 'standard output'); # always go to stdout
$| = 1 if $unbuffer;

for (@ARGV) {
    if (!open($fh, (/^[^>|]/ && $mode) . $_)) {
	warn "$0: cannot open $_: $!\n"; # like sun's; i prefer die
	$status++;
	next;
    }
    select((select($fh), $| = 1)[0]) if $unbuffer;
    $fh{$fh++} = $_;
} 
while (<STDIN>) {
    for $fh (keys %fh) {
	print $fh $_;
    } 
} 
for $fh (keys %fh) { 
    close($fh) && next;
    warn "$0: couldn't close $fh{$fh}: $!\n";
    $status++;
}
exit $status;
--
Tom Christiansen		tchrist at convex.com	convex!tchrist
	    "Perl is to sed as C is to assembly language."  -me



More information about the Alt.sources mailing list