For the reader's sake (since OP already "got it working"):
The Perl documentation, "perlopentut" (perldoc perlopentut) gives examples of opening an alternate filehandle directed to STDOUT, but it uses bareword filehandles, and the two-arg version of open
, both of which are somewhat ancient. Damian Conway's book "Perl Best Practices" (as well as Perl::Critic, which is based on Damian's book) emphasizes using three arg opens and lexical filehandles (my $foo
style filehandles). chromatic's "Modern Perl" also briefly mentions using lexical filehandles, and discourages barewords where practical. The three arg open
is considered to be a safer form, as it limits exposure to shell injections. While the specific case here is low risk, it's still a good habit to default to the three-arg open
.
It takes careful reading of the examples shown in Perl's open
documentation (perldoc -f open), and a little interpretation to notice the correct placement of the ampersand character in opening a duplicate filahandle directed to STDOUT
when using the three-arg version of open
. One might errantly assume that this should work: open my $fh, '>', '&STDOUT' or die $!;
, mostly because it looks like a format we're used to seeing (ampersand preceding a symbol name). But that syntax isn't what open
needs, and we're used to seeing it in an entirely different context: certain subroutine calls.
The correct way to open a dupe to STDOUT
with the three arg open
is to combine the >
and the &
into the same second argument, and leave STDOUT bare, like this:
use Modern::Perl;
open my $fh, '>&', STDOUT or die "Bleah: $!";
say $fh 'Printing alternate filehandle "$fh" worked.';
say 'Implicitly printing to "STDOUT" also works.';
Or passing STDOUT
to open
as a reference to the typeglob:
open my $fh, '>&', \*STDOUT or ...
... } else { open($fh, '>&' . fileno(STDOUT)); }
– Germann