Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Re^2: get directory listing

by bluto (Curate)
on Nov 08, 2005 at 16:31 UTC ( [id://506787]=note: print w/replies, xml ) Need Help??


in reply to Re: get directory listing
in thread get directory listing

Whatever, I really wonder why people insist so much in reinventing the wheel where a simple glob would do.

That's because a simple glob will get you in trouble in production code. For example...

my @dirs=grep -d, </usr/darren/*>; # Whoa it's one line!!

Yeah it's on one line and looks elegant. Unfortunately there is no error control and it skips directories with a leading '.' in the name (e.g. '.foo', '..bar'). With readdir you need to be a little careful, but it works fine. If you aren't chdir'd into the directory you are reading you generally need to prepend the directory path to each name it returns, but that's trivial.

Replies are listed 'Best First'.
Re^3: get directory listing
by blazar (Canon) on Nov 08, 2005 at 16:52 UTC
    Yeah it's on one line and looks elegant. Unfortunately there is no error control and it skips directories with a leading '.' in the name (e.g. '.foo', '..bar').
    1. From perldoc File::Glob:
      The POSIX defined flags for bsd_glob() are: "GLOB_ERR" Force bsd_glob() to return an error when it encounters a directory it cannot open or read. Ordinarily bsd_glob() continues to find matches.
    2. Skipping directories with a leading dot may be a feature. One can glob '.*' if need be.
    Not to say that there are not situations in which an explicit opendir & C. is actually preferrable. Indeed there are. My point being that in the vast majority of cases a simple glob would do instead. I think OTOH it has a stigma due to the fact that anciently it relied on a call to an external shell, which is what I read it in a book, but since I don't have effective experiennce with Perl 4, the last one that I think was set up like that, I cannot tell for sure...
      From perldoc File::Glob: ...

      Your one liner is no longer really one line if you go that way. For the OP's solution, you'll need to be able to construct some magic looking glob string with '*' and '.*', and you'll have to weed out '.' and '..' as well. Assuming you can do that easily, you'll have something like this...

      use File::Glob ':glob'; my @dirs = grep { -d } bsd_glob('/usr/darren/' . $some_magic_globstr_h +ere, GLOB_ERR); die "glob: $!" if GLOB_ERROR;
      ... which IMHO isn't shorter or easier to comprehend/maintain than this ...
      opendir my $dh, /usr/darren' or die "opendir: $!"; my @dirs = grep { -d } map { "/usr/darren/$_" } grep { !/^\.\.?$/ } re +addir $dh; closedir $dh or die "closedir: $dh"; # this line optional
      ... esp if you have to change what is matched in the future, but YMMV.
        Your one liner is no longer really one line if you go that way. For the OP's solution, you'll need to be able to construct some magic looking glob string with '*' and '.*', and you'll have to weed out '.' and '..' as well. Assuming you can do that easily, you'll have something like this...

        Fair enough! (++)

        However in my experience (but YMMV too!) I've found that in the vast majority of cases you either want:

        1. files after some definite name pattern in a given directory (e.g.: 'log--*'), or
        2. all files in a given directory hierarchy. In which case I usually resort to plain File::Find, although its "enhanced" cousins would do.

        Incidentally the "magic looking glob string" is nothing but '* .*'.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://506787]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (5)
As of 2024-04-20 02:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found