Printing to multiple files ... without changing my code.

Joel Bernstein joel at fysh.org
Fri Sep 15 14:47:46 BST 2006


On Fri, Sep 15, 2006 at 12:48:18PM +0100, McGlinchy, Alistair wrote:
> Hi all,
> 
> I have some code with print statements liberally sprinkled throughout
> (180 locations at last count).  I now need to have this code write to a
> production and development box every time it runs. It's likely that the
> number of locations could grow so can someone please advise what is the
> standard idiom for making my standard "print"s go to multiple files? 
> 
> I know I can roll my own "tee" sub, I just want to know if there's a way
> of doing this without having to change all the print throughout my code
> to my_tee statements. 
> 
> I've also seen IO::Tee on CPAN but that will also require changing my
> code ... won't it?
> 
> my @files    = qw( pie.txt pony.txt buffy.txt);
> my @handles  = map {open my $x, ">>$_" or die $!; $x} @files;
> #... <magic>...
> print "Hello\n";  #Magically written to all @files
> close $_ for @handles;

That isn't going to work. Nor will overloading *CORE::print() because
print is magical (consider how it behaves with print $foo vs print FILE
$foo). I'd say the best way is to tie STDOUT, which I've just hacked up
a demo of:

joel at wombat 14:44 /tmp/lib $ cat Tie/Stdout.pm
package Tie::Stdout;
use strict;
use warnings;

our $stdout = "";
our @fh = ();

sub TIEHANDLE { bless {}, shift }
sub PRINT { shift; $stdout .= join '', @_ }
sub import {
        my $class = shift;
        return unless @_;
        for my $file (@_) {
                open my $fh, ">>", $file or die $!;
                push @fh, $fh;
        }
        unless (ref tied *STDOUT eq $class) {
                tie *STDOUT, $class or die "couldn't tie: $!";
        }
}

END { for my $fh (@fh) { print $fh $stdout } }

1;
----------------------------8<--------------------------------
joel at wombat 14:44 /tmp/lib $ perl -I. -l 
use Tie::Stdout qw(/tmp/foo /tmp/bar); 
print "foo";
^D
joel at wombat 14:45 /tmp/lib $ cat ../foo
foo
joel at wombat 14:46 /tmp/lib $ cat ../bar
foo

Does that work for you? If I've misunderstood the problem, please
restate it :)

/joel


More information about the london.pm mailing list