
![]() | ![]() |
7.10. Copying Filehandles
7.10.1. Problem
You want a copy of a filehandle.
7.10.2. Solution
To create an alias for a named filehandle, say:*ALIAS = *ORIGINAL;
Use open with the & file
access mode to create an independent copy of the file descriptor for
that 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 or 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: $!";
With other types of filehandles (typeglobs, objects), use the same
technique with a three-argument open:open(my $copy, "<&", $original) or die "Couldn't alias original: $!";
open(my $copy, "<&=", $original) or die "Couldn't alias original: $!";
7.10.3. Discussion
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 further attempt to use a copy of that
filehandle fails, silently by default or, if you have warnings
enabled, with the warning "print
on closed
filehandle". When alternating access through
aliased filehandles, writes work as you'd expect because there are no
duplicated stdio data structures 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) syscall. 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
for a file descriptor using open(ALIAS,
">&=HANDLE"), you're really calling the
fdopen(3) function from the stdio library or its
equivalent. 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 failed. 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.9 for more information on this.
7.10.4. See Also
The open function in
perlfunc(1) and in Chapter 29 of
Programming Perl; your system's
dup(2) manpage
![]() | ![]() | ![]() |
7.9. Opening and Closing File Descriptors by Number | ![]() | 7.11. Creating Temporary Files |

Copyright © 2003 O'Reilly & Associates. All rights reserved.