From: Tom Christiansen <tchrist@mox.perl.com>
Subject: SRC: printing to more than one filehandle
Date: 22 May 1998 13:50:20 GMT
Ever want one filehandle to connect to more than one file?
You could do this:
for $fh (*FH1, *FH2, *FH3) { print $fh "whatever\n" }
or you could do this:
open(MANY, "| tee file1 file2 file3 > /dev/null") || die $!;
print MANY "data\n" or die $!;
close(MANY) || die $!;
Or you could use a tied filehandle:
use Tie::Tee;
use Symbol;
@handles = (*STDOUT);
for $i ( 1 .. 10 ) {
push(@handles, $handle = gensym());
open($handle, ">/tmp/teetest.$i");
}
tie *TEE, 'Tie::Tee', @handles;
print TEE "This lines goes many places.\n";
Using this module:
package Tie::Tee;
sub TIEHANDLE {
my $class = shift;
my $handles = [@_];
bless $handles, $class;
return $handles;
}
sub PRINT {
my $href = shift;
my $handle;
my $success = 0;
foreach $handle (@$href) {
$success += print $handle @_;
}
return $success == @$href;
}
1;
Or you could have your own tee program, which is more powerful than
the regular one,
$ command | tctee file1 ">>file2" "|cmd" file3 "|cmd3" file4
using the tctee program below:
#!/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);
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: couldn't close $fh{$fh}: $!\n";
$status++;
}
exit $status;
sub PLUMBER {
warn "$0: pipe to \"$fh{$fh}\" broke!\n";
$status++;
delete $fh{$fh};
}
--
MS-DOS is CP/M on steroids, bigger bulkier and not much better.
Windows is MS-DOS with a bad copy of a Macintosh GUI.
NT is a Windows riddled with VMS.