Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

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.

Log In?

What's my password?
Create A New User
Domain Nodelet?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (3)
As of 2024-06-25 17:19 GMT
Find Nodes?
    Voting Booth?

    No recent polls found

    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.