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
| [reply] [Watch: Dir/Any] [d/l] |
|
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
| [reply] [Watch: Dir/Any] [d/l] |
|
| [reply] [Watch: Dir/Any] |
|
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
| [reply] [Watch: Dir/Any] |
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);
| [reply] [Watch: Dir/Any] [d/l] [select] |
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
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
(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?
| [reply] [Watch: Dir/Any] [d/l] |
|
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
| [reply] [Watch: Dir/Any] |
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' | [reply] [Watch: Dir/Any] [d/l] [select] |
|
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)
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] [d/l] |