start page | rating of books | rating of authors | reviews | copyrights

Perl Cookbook

Perl CookbookSearch this book
Previous: 8.18. Program: tailwtmp Chapter 8
File Contents
Next: 8.20. Program: laston
 

8.19. Program: tctee

Not all systems support the classic tee program for splitting output pipes to multiple destinations. This command sends the output from someprog to /tmp/output and to the mail pipe beyond.

% someprog | tee /tmp/output | Mail -s 'check this' [email protected]

This program helps not only users who aren't on Unix systems and don't have a regular tee . It also helps those who are, because it offers features not found on other version of tee .

The four flag arguments are -i to ignore interrupts, -a to append to output files, -u for unbuffered output, and -n to omit copying the output on to standard out.

Because this program uses Perl's magic open, you can specify pipes as well as files.

% someprog | tctee f1 "|cat -n" f2 ">>f3"

That sends the output from someprog to the files f1 and f2 , appends it to f3 , sends a copy to the program cat -n , and also produces the stream on standard output.

The program in Example 8.8 is one of many venerable Perl programs written nearly a decade ago that still runs perfectly well. If written from scratch now, we'd probably use strict , warnings, and ten to thirty thousand lines of modules. But if it ain't broke . . .

Example 8.8: tctee

#!/usr/bin/perl # tctee - clone that groks process tees  # perl3 compatible, or better.  while ($ARGV[0] =~ /^-(.+)/ && (shift, ($_ = $1), 1)) {     next if /^$/;     s/i// && (++$ignore_ints, redo);     s/a// && (++$append,      redo);     s/u// && (++$unbuffer,    redo);     s/n// && (++$nostdout,    redo);     die "usage tee [-aiun] [filenames] ...\n"; }  if ($ignore_ints) {     for $sig ('INT', 'TERM', 'HUP', 'QUIT') { $SIG{$sig} = 'IGNORE'; } }  $SIG{'PIPE'} = 'PLUMBER'; $mode = $append ? '>>' : '>'; $fh = 'FH000';  unless ($nostdout) {     %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) {     next if close($fh) || !defined $fh{$fh};     warn "$0: couldnt close $fh{$fh}: $!\n";     $status++; }  exit $status;  sub PLUMBER {     warn "$0: pipe to \"$fh{$fh}\" broke!\n";     $status++;     delete $fh{$fh}; }




Previous: 8.18. Program: tailwtmp Perl Cookbook Next: 8.20. Program: laston
8.18. Program: tailwtmp Book Index 8.20. Program: laston