Bignut_Squirrel has asked for the wisdom of the Perl Monks concerning the following question:

Monks,

My script needs to read all the files in a directory into an array for comparison. This works when I directly provide the path to the directory as below:

@filearray = </var/log/*>;

I want to make the code more flexible so I need to store the directory in a variable instead, but this way does not seem to work:

$path = '/var/log/*'; @filearray = <$path>;

This results in an empty array. I have tried different quotations, but I can't figure out the syntax. Is there a way to do this?

Replies are listed 'Best First'.
Re: Reading a directory into an array using <>
by toolic (Bishop) on Jun 16, 2011 at 19:55 UTC
    If you use warnings, you should get a warning message like:
    readline() on unopened filehandle at ...
    Also, if you use diagnostics, you should get a little more help on that message:
    readline() on unopened filehandle at ... (#1) (W unopened) An I/O operation was attempted on a filehandle that w +as never initialized. You need to do an open(), a sysopen(), or a so +cket() call, or call a constructor from the FileHandle package.
    Well, those might not be the most helpful messages to you, but at least they give you an idea that something is amiss. To avoid the voodoo of <>, use glob:
    use warnings; use strict; my $path = '/var/log/*'; my @files = grep { -f } glob $path;
    See also:
Re: Reading a directory into an array using <>
by Marshall (Canon) on Jun 16, 2011 at 19:45 UTC
    to say get only the directories in my temp directory, you can use the glob() function:
    #!/usr/bin/perl -w use strict; my $path = 'C:/temp/'; my @filearray = grep{-d}glob("$path*"); print join("\n",@filearray);
Re: Reading a directory into an array using <>
by 7stud (Deacon) on Jun 16, 2011 at 20:30 UTC
    If the string(sic --> should be 'thing') inside the angle brackets is anything other than a filehandle name or a scalar variable (even if there are just extra spaces), it is interpreted as a filename pattern to be 'globbed'. (Programmig Perl, p. 83)

    You have a scalar variable inside the angle brackets, so it is *not* interpreted as a filename pattern to be globbed.

    You could trick perl like this:

    my @fnames = <${path}>

    But since the angle operator calls glob() implicitly when you don't provide it with a file handle or scalar variable inside the brackets, you might as well just call glob() explicitly yourself. Note that the argument to glob() is a string, so you need quotes.

    You can also use opendir() and readdir():

    use strict; use warnings; use 5.010; my $path = '/var/log'; opendir(my $TARGET_DIR, $path) or die "Couldn't open directory $path: $!"; my @all_files = readdir $TARGET_DIR; closedir $TARGET_DIR;

    There are a couple of differences, though: 1) glob() will ignore invisible files, 2) glob() tacks the file name onto the specified path, where readdir() just returns the filenames.