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

Hello,

This is perhaprs a very simple question. However I would like to automatically list the files in a directory an store them in array. So I use globbing, which I do as follows:

@files=</path/to/dir/*.type>

That works out well. The problem I have is that I what to give it variable (which is taken is as a parameter by the perl script. This however doesn't appear to work. I am doing the following

$path_to_dir = $ARGV[0];

@files=<$path_to_dir>

Any advice on how this could work..?

THANKS!

Replies are listed 'Best First'.
Re: Globbing uncertainty
by Tanktalus (Canon) on Nov 11, 2010 at 18:14 UTC

    Never, ever use <> for globbing. Always always use glob instead. Gets rid of all ambiguity.

    As jethro said, your variable name implies that it's just a directory you're getting, so you still have to add the "/*.type" inside your code. If the user is passing in the * on the command line, then what you have would work if you switched over to glob. What you have right now looks to me like the perl compiler is treating $path_to_dir as if it were a filehandle and trying to read all lines from that filehandle. Using glob eliminates the confusion.

      If the user is passing in the * on the command line, then what you have would work if you switched over to glob.

      Assuming it was quoted. If it wasn't quoted, and one isn't using the Windows command shell, the shell would have done the globbing itself.

      $ perl -E'say for @ARGV' 'tmp/*' tmp/* $ perl -E'say for @ARGV' tmp/* tmp/a tmp/b tmp/c tmp/d tmp/e
Re: Globbing uncertainty
by jethro (Monsignor) on Nov 11, 2010 at 18:01 UTC
    @files=<$path_to_dir/*>
Re: Globbing uncertainty
by Marshall (Canon) on Nov 11, 2010 at 19:36 UTC
    Another way to go is to stay away from glob() altogether. There are several versions of glob() and they are a bit different. Open the directory using your $path_to_dir and then use grep{} to get what you want:

    @files = grep{-f "$path_to_dir/$_"}readdir Dir;
    of course you can add a regex or any other code you like inside the grep{}.

      In my experience, readdir is almost never what you want. Use glob. Really, it's much easier, and it keeps the full pathname that is fed to it. Your @files array will hold only the filenames, not $path_to_dir. In order for it to be useful, you almost always will need to concatenate $path_to_dir to each item in the array anyway. Since that is probably the case, just use glob and the list you get back will already have the pathname in there, and the values will be useful immediately.

        In my experience, glob() is almost never a good idea for me - I used to think that it was until I gained more experience and got bitten by this critter a few times. So we just disagree a bit.

        For example, I've had trouble with ActiveState's glob vs BSD glob vs Posix glob and some pretty strange things have happened when my code wouldn't run on some other guy's windows box as a PerlApp.exe. Anyway haven been bitten a couple of times with cross platform weirdness, I am leery of glob(). Yes, to say open the file, you do indeed have to concatenate the $dirpath name. "$dirpath/$file". Lots of times I need to process the $filename (maybe update some serial number in it), which if full path, needs Basename or such to get the filename, or I need a more complex regex than what the simple glob() thing does or some other file test (like on modification date). Things like: Re: opening accented file names come up also.

        Anyway, the OP now knows a couple of ways. And can choose the tool that best fits the job at hand. I certainly am not saving never use glob() or always use readdir(). Always and never are two words that don't fit with programming.

Re: Globbing uncertainty
by Anonymous Monk on Nov 11, 2010 at 23:59 UTC
    glob doesn't take paths, glob takes patterns, and back slashes escape glob meta characters
    $ perl -le"print for glob shift" C:\perl\[5]*\bin $ perl -le"print for glob shift" C:\perl\\[5]*\bin C:\perl\5.10.1\bin C:\perl\5.11.1\bin C:\perl\5.12.2\bin $ perl -le"print for glob shift" C:\perl/[5]*\bin C:\perl/5.10.1\bin C:\perl/5.11.1\bin C:\perl/5.12.2\bin
    So you need to escape $path_to_dir according to your glob rules or
    chdir $path_to_dir ; glob '*.type';
    I think glob is neat, but the syntax can get complicated , after all it is a shell mini language, for advanced computer users.