Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

special directory entries

by cybermack72 (Novice)
on Dec 04, 2001 at 01:05 UTC ( [id://129180]=perlquestion: print w/replies, xml ) Need Help??

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

How can I read a directory without the script reading those dagumb "." and ".." entries into the array. I know chdir helps. When I use readdir, however, it returns both files and these sill entries.

Replies are listed 'Best First'.
Re: special directory entries
by jwest (Friar) on Dec 04, 2001 at 01:12 UTC
    You're better off to just strip . and .. out as they come in. Something like:
    @dirs = grep(!/^\.\.?$/, readdir(DIR));
    would do it nicely.

    Hope this helps!

    --jwest

    -><- -><- -><- -><- -><-
    All things are Perfect
        To every last Flaw
        And bound in accord
             With Eris's Law
     - HBT; The Book of Advice, 1:7
    
      Why do people keep trotting out this readdir-and-regexp idiom to deal with current and parent directories?

      @dirs = grep($_ ne '.' and $_ ne '..', readdir(DIR));

      Sure it's a little more verbose, but it doesn't suffer from sneaky boundary failures (that blakem points out elsewhere in this thread). While it's more verbose, it's also more efficient, as it doesn't need regexp machinery.

      Of course, that should be File::Spec::curdir and File::Spec::updir, to be on the safe side.

      To find out FMTYEWTK about readdir, '.' and '..', I recommend reading this thread, especially merlyn's reply.

      --
      g r i n d e r
      just another bofh
      Anything for Win32...?
        As far as I know, this should be portable to Win32. Unless grep isn't implemented there, but I believe it to be. If you let me know where this fails on Win32, I might be able to help.

        Also, wog's solution below looks like it will handle any portability issues transparently.

        --jwest


        -><- -><- -><- -><- -><-
        All things are Perfect
            To every last Flaw
            And bound in accord
                 With Eris's Law
         - HBT; The Book of Advice, 1:7
        
Re: special directory entries
by wog (Curate) on Dec 04, 2001 at 02:03 UTC
    You can also do this with File::Spec's no_upwards function:

    use File::Spec; ... my @entries = File::Spec->no_upwards(readdir DIR);
Re: special directory entries
by blakem (Monsignor) on Dec 04, 2001 at 02:13 UTC
    One thing to watch out for though, the regex /^\.\.$/ wont do the right thing with a file named ".\n" or "..\n".
    #!/usr/bin/perl -wT use strict; my @arr = (".", "..", ".\n", "..\n", "file.txt"); my @files = grep !/^\.\.?$/, @arr; print "'$_'\n" for @files; # <== only prints 'file.txt'
    A better regex would be /^\.\.?\z/ since it will deal with these odd filenames correctly.

    Update: Reworded the first sentence, since it was rather unclear.

    -Blake

      (Update: I guess I missed the last line of your comment, and for some reason interpreted your comment to mean exactly the opposite of what you were trying to say, so disregard this note! Sorry.)

      Under what conditions would a file named "..\n" exist, and why would you necessarily want to omit it? If you're looking to get at all files in a directory, but skip the special . and .., and you still want to get files that someone's done crazy stuff with, you wouldn't necessarily want to omit these.

      Or am I misunderstanding something?

        If a malicious hacker creates a file (or directory) called ".\n" a monitoring script using /^\.\.$/ will lump it in with '.' and '..' and skip right over it.

        -Blake

Re: special directory entries
by rob_au (Abbot) on Dec 04, 2001 at 01:15 UTC
    A slight variation on code from the perlfunc:readdir documentation page ...

    opendir (DH, $directory); my @files = grep { -f "$directory/$_" } readdir(DH); close (DH);

    Note that this code returns *only* the files from the directory, ignoring both the parent path 'dot' entries and sub-directory entries. If you want the sub-directory entries, change the grep code to read -

    my @entries = grep { /^\.+$/ } readdir(DH);

     

    perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'

      my @entries = grep { /^\.+$/ } readdir(DH);
      Not to be too pedantic, but this code isn't particularly useful. It gives back all of the entries that consist only of dots (and, well, we know they're there!). I think you meant:
      # Everything that isn't just dots. my @e = grep { ! /^\.+$/ } readdir(DH);
      Because then your explanation matches your code. Or maybe even:
      # Everything that doesn't begin with . or .. (better!) my @e = grep { ! /^\.\.?$/ } readdir(DH);
      Because this would then eliminate "..." as a "system directory entry." (... is great for hiding things)
        You are correct ... I had meant to write ...

        my @entries = grep { ! /^\.+$/ } readdir(DH);

        That's what you get for coding before the morning coffee ... Thanks clintp++

         

        perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (4)
As of 2024-03-29 07:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found