Tom Christiansen <tchrist@convex.COM> (06/06/91)
(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@leland.Stanford.EDU (Dave Eisen): :In article <1991Jun6.093939.9346@dartvax.dartmouth.edu> pete@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@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@convex.com convex!tchrist "Perl is to sed as C is to assembly language." -me