You want to make a copy of a filehandle.
To create an alias for a filehandle, say:
*ALIAS = *ORIGINAL;
Use
open
with the
&
mode to create an independent copy of the file descriptor for the filehandle:
open(OUTCOPY, ">&STDOUT") or die "Couldn't dup STDOUT: $!"; open(INCOPY, "<&STDIN" ) or die "Couldn't dup STDIN : $!";
Use
open
with the
&=
mode to create an alias for that filehandle's file descriptor:
open(OUTALIAS, ">&=STDOUT") or die "Couldn't alias STDOUT: $!"; open(INALIAS, "<&=STDIN") or die "Couldn't alias STDIN : $!"; open(BYNUMBER, ">&=5") or die "Couldn't alias file descriptor 5: $!";
If you create an alias for a filehandle with
typeglobs, only one Perl I/O object is still being accessed. If you close one of these aliased filehandles, the I/O object is closed. Any subsequent attempt to use a copy of that filehandle will give you an error like
"print
on
closed
filehandle"
. When alternating access through the aliased filehandles, writes work as you'd expect because there's no duplicated stdio data structure to get out of sync.
If you create a copy of a file descriptor with
open(COPY,
">&HANDLE")
, you're really calling the
dup
(2) system call. You get two independent file descriptors whose file position, locks, and flags are shared, but which have independent stdio buffers. Closing one filehandle doesn't affect its copy. Simultaneously accessing the file through both filehandles is a recipe for disaster. Instead, this technique is normally used to save and restore STDOUT and STDERR:
# take copies of the file descriptors open(OLDOUT, ">&STDOUT"); open(OLDERR, ">&STDERR"); # redirect stdout and stderr open(STDOUT, "> /tmp/program.out") or die "Can't redirect stdout: $!"; open(STDERR, ">&STDOUT") or die "Can't dup stdout: $!"; # run the program system($joe_random_program); # close the redirected filehandles close(STDOUT) or die "Can't close STDOUT: $!"; close(STDERR) or die "Can't close STDERR: $!"; # restore stdout and stderr open(STDERR, ">&OLDERR") or die "Can't restore stderr: $!"; open(STDOUT, ">&OLDOUT") or die "Can't restore stdout: $!"; # avoid leaks by closing the independent copies close(OLDOUT) or die "Can't close OLDOUT: $!"; close(OLDERR) or die "Can't close OLDERR: $!";
If you create an alias of a file descriptor using
open(ALIAS,
">&=HANDLE"
), you're really calling the
fdopen
(3) stdio function. You get a single file descriptor with two stdio buffers accessed through two filehandles. Closing one filehandle closes the file descriptor of any aliases, but not their filehandles - if you tried to
print
to a filehandle whose alias had been
close
d, Perl wouldn't give a
"print on closed filehandle warning"
even though the
print
didn't succeed. In short, accessing the file through both filehandles is also a recipe for disaster. This is really used only to open a file descriptor by number. See
Recipe 7.19
for more information on this.
The
open
function in
perlfunc
(1) and in
Chapter 3
of
Programming Perl
; your system's
dup
(2) manpage