Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

How can I make a filehandle local to a subroutine? How do I pass filehandles between subroutines? How do I make an array of filehandles?

by faq_monk (Initiate)
on Oct 08, 1999 at 00:23 UTC ( [id://649] : perlfaq nodetype . print w/replies, xml ) Need Help??

Current Perl documentation can be found at

Here is our local, out-dated (pre-5.6) version:

The fastest, simplest, and most direct way is to localize the typeglob of the filehandle in question:

    local *TmpHandle;

Typeglobs are fast (especially compared with the alternatives) and reasonably easy to use, but they also have one subtle drawback. If you had, for example, a function named TmpHandle(), or a variable named %TmpHandle, you just hid it from yourself.

    sub findme {
        local *HostFile;
        open(HostFile, "</etc/hosts") or die "no /etc/hosts: $!";
        local $_;               # <- VERY IMPORTANT
        while (<HostFile>) {
            print if /\b127\.(0\.0\.)?1\b/;
        # *HostFile automatically closes/disappears here

Here's how to use this in a loop to open and store a bunch of filehandles. We'll use as values of the hash an ordered pair to make it easy to sort the hash in insertion order.

    @names = qw(motd termcap passwd hosts);
    my $i = 0;
    foreach $filename (@names) {
        local *FH;
        open(FH, "/etc/$filename") || die "$filename: $!";
        $file{$filename} = [ $i++, *FH ];

    # Using the filehandles in the array
    foreach $name (sort { $file{$a}[0] <=> $file{$b}[0] } keys %file) {
        my $fh = $file{$name}[1];
        my $line = <$fh>;
        print "$name $. $line";

For passing filehandles to functions, the easiest way is to prefer them with a star, as in func(*STDIN). See Passing Filehandles for details.

If you want to create many, anonymous handles, you should check out the Symbol, FileHandle, or IO::Handle (etc.) modules. Here's the equivalent code with Symbol::gensym, which is reasonably light-weight:

    foreach $filename (@names) {
        use Symbol;
        my $fh = gensym();
        open($fh, "/etc/$filename") || die "open /etc/$filename: $!";
        $file{$filename} = [ $i++, $fh ];

Or here using the semi-object-oriented FileHandle, which certainly isn't light-weight:

    use FileHandle;

    foreach $filename (@names) {
        my $fh = FileHandle->new("/etc/$filename") or die "$filename: $!";
        $file{$filename} = [ $i++, $fh ];

Please understand that whether the filehandle happens to be a (probably localized) typeglob or an anonymous handle from one of the modules, in no way affects the bizarre rules for managing indirect handles. See the next question.