Recipe 7.8 Printing to Many Filehandles Simultaneously

7.8.1 Problem

You need to output the same data to several different filehandles.

7.8.2 Solution

If you want to do it without forking, write a foreach loop that iterates across the filehandles:

foreach $filehandle (@FILEHANDLES) {
    print $filehandle $stuff_to_print;
}

If you don't mind forking, open a filehandle that's a pipe to a tee program:

open(MANY, "| tee file1 file2 file3 > /dev/null")   or die $!;
print MANY "data\n"                                 or die $!;
close(MANY)                                         or die $!;

If you don't have a tee program handy, use the IO::Tee module from CPAN:

use IO::Tee;
$tee = IO::Tee->new(@FILEHANDLES);
print $tee $stuff_to_print;

7.8.3 Discussion

A filehandle sends output to one file or program only. To duplicate output to several places, you must call print multiple times or make a filehandle connected to a program like tee, which distributes its input elsewhere. If you use the first option, it's probably easiest to put the filehandles in a list or array and loop through them (see Recipe 7.5):

for $fh (*FH1, *FH2, *FH3)      { print $fh "whatever\n" }

However, if your system supports the tee(1) program, or if you've installed the Perl version from Recipe 8.25, you may open a pipe to tee and let it do the work of copying the file to several places. Remember that tee normally also copies its output to STDOUT, so you must redirect tee's standard output to /dev/null if you don't want an extra copy:

open (FH, "| tee file1 file2 file3 >/dev/null");
print FH "whatever\n";

You could even redirect your own STDOUT to the tee process, and then you're able to use a regular print directly:

# make STDOUT go to three files, plus original STDOUT
open (STDOUT, "| tee file1 file2 file3") or die "Teeing off: $!\n";
print "whatever\n"                       or die "Writing: $!\n";
close(STDOUT)                            or die "Closing: $!\n";

The IO::Tee module from CPAN gives you a single filehandle (an object of the IO::Tee class) that you can write to. The object prints to many different filehandles whatever you print to it. Pass destination filehandles to the constructor:

use IO::Tee;

$t = IO::Tee->new(*FH1, *FH2, *FH3);
print $t "Hello, world\n";
print $t "Goodbye, universe\n";

In addition to print, you can do any I/O operation you like to an IO::Tee filehandle. For example, if you close $t in the preceding example, the close will return true if FH1, FH2, and FH3 were all successfully closed.

7.8.4 See Also

The print function in perlfunc(1) and in Chapter 29 of Programming Perl; the "Typeglobs and Filehandles" sections of Chapter 2 of Programming Perl; the documentation for the CPAN module IO::Tee; we use this technique in Recipe 8.25 and Recipe 13.15