How does Perl sort array in opendir by default?

M

Mike

I'm using opendir to open a series of files in a directory, but
they're not being sorted by default the way I thought they would.

I have 3 files:
aaa.txt (765 bytes)
bbb.txt (977 bytes)
ccc.txt (10161 bytes)

I assumed that it would enter them into the array alphabetically, but
instead they went in ccc,aaa,bbb!

Is there a method to this madness? Coincidentally, it's being sorted
exactly like I want right now, but I'm not sure what will happen when
a 4th file is added.

TIA,

Mike


PS, the exact code is:

opendir FILENAMES, "$basepath";
@data= readdir FILENAMES;
closedir FILENAMES;
 
U

Uri Guttman

M> I'm using opendir to open a series of files in a directory, but
M> they're not being sorted by default the way I thought they would.

M> I assumed that it would enter them into the array alphabetically, but
M> instead they went in ccc,aaa,bbb!

where did you read in the docs that this was the case? or who taught you
that mistaken factoid?

perldoc -f readdir doesn't mention the term sort. did you check out that
doc before you made public your incorect assumption?

and there was a thread on this in the last week. try googling for it

uri
 
S

Sherm Pendley

I assumed that it would enter them into the array alphabetically

Why did you assume that? Nothing in the docs for readdir says anything
about them being sorted.

If you want them sorted, you have to sort them yourself; for a simple
alphabetic sort, this could be as simple as:

my @files = sort(readdir(FILENAMES));

sherm--
 
M

Mike

I assumed that it would enter them into the array alphabetically
Why did you assume that? Nothing in the docs for readdir says anything
about them being sorted.

I knew that perldoc didn't say anything, I was just making an
assumption because my server lists all of the files alphabetically by
default when you telnet in. Plus, I had no other reason to believe
otherwise. Just an assumption.
If you want them sorted, you have to sort them yourself; for a simple
alphabetic sort, this could be as simple as:

my @files = sort(readdir(FILENAMES));

Of course, which would sort them alphabetically, or whatever you make
it do. In this case, I would prefer them to be sorted by
last-date-modified, and that's why I ask; if this is how they're
sorted by default, then there's no need for me to code it.

To Uri (who also replied), when I searched for "sort opendir array,"
the most recent post to come up was from 2002. Can you be more
specific about the similar recent post?

Mike
 
P

Paul Lalli

Of course, which would sort them alphabetically, or whatever you make
it do. In this case, I would prefer them to be sorted by
last-date-modified, and that's why I ask; if this is how they're
sorted by default, then there's no need for me to code it.

To Uri (who also replied), when I searched for "sort opendir array,"
the most recent post to come up was from 2002. Can you be more
specific about the similar recent post?

untested:

my @files = sort {-M $a <=> -M $b} readdir(FILENAMES);


This puts the most recently modified at the beginning of the list. For
the reverse, swap $a and $b above.

The default is whatever order they are returned by your operating system.
This could changed depending on what system your script is run on.
Therefore, trusting the default to be what you want is A Bad Idea.

Paul Lalli
 
W

Walter Roberson

:my @files = sort {-M $a <=> -M $b} readdir(FILENAMES);


:This puts the most recently modified at the beginning of the list.

Schwartzian Transform unless you don't mind exponential numbers of
stat()'s.
 
R

Randal L. Schwartz

Mike> I knew that perldoc didn't say anything, I was just making an
Mike> assumption because my server lists all of the files alphabetically by
Mike> default when you telnet in. Plus, I had no other reason to believe
Mike> otherwise. Just an assumption.

But "ls" is doing the sorting. If you give ls the -f switch, it
presents unsorted. Also, find shows you the unsorted order as well.

readdir() returns the results unsorted because sorting is extra work,
and if you're going to do something to every element anyway, it doesn't
matter what order. :)

print "Just another Perl hacker,"
 
T

Tassilo v. Parseval

Also sprach Walter Roberson:
:my @files = sort {-M $a <=> -M $b} readdir(FILENAMES);


:This puts the most recently modified at the beginning of the list.

Schwartzian Transform unless you don't mind exponential numbers of
stat()'s.

Exponential?

Tassilo
 
P

Paul Lalli

:my @files = sort {-M $a <=> -M $b} readdir(FILENAMES);


:This puts the most recently modified at the beginning of the list.

Schwartzian Transform unless you don't mind exponential numbers of
stat()'s.

Quite correct. I should have done it with a transform in the first place:

(still untested):

my @files = map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [ $_, -M ] }
readdir FILENAMES;


Paul Lalli.
 
P

pkent

I'm using opendir to open a series of files in a directory, but
they're not being sorted by default the way I thought they would.

Sorry to break it to you but computers have a habit of sucking, and of
not doing what you want them to. Or even worse, doing exactly what you
tell them to. :)

You said that the computer didn't do what you thought it'd do. Even
perldoc -f readdir doesn't mention the order of entries (on my system at
least). But perl can help, using the sort() function built in to perl -
e.g.:

@filenames = sort @filenames;

for the default sorting order. If that's not good for you, you can
define your own sorting routine.

P
 
W

Walter Roberson

:> Schwartzian Transform unless you don't mind exponential numbers of
:> stat()'s.

:Exponential?

For small exponents ;-)

perldoc on sort says that it used to use quicksort, worst case O(N**2),
and now uses a mergesort, worst case O(N * log N) unless you request
quicksort specifically.
 
T

Tad McClellan

Mike said:
Subject: How does Perl sort array in opendir by default?


Perl does not determine what order they are in.

The Operating System determines what order they are in.

PS, the exact code is:

opendir FILENAMES, "$basepath";


You should check the return value from opendir().

You should NOT use useless double quotes.


opendir FILENAMES, $basepath or die "could not open '$basepath' dir $!";

@data= readdir FILENAMES;


@data= sort readdir FILENAMES;


We gotta kind of wonder why you couldn't come up with that yourself...
 
C

Chris Mattern

Mike said:
I knew that perldoc didn't say anything, I was just making an
assumption because my server lists all of the files alphabetically by
default when you telnet in.

I presume you mean when you use an ls command. A "man ls" would
reveal that the documentation *tells* you ls sorts by filename by
default.
Plus, I had no other reason to believe
otherwise. Just an assumption.

Why would you assume that? The documentation makes no mention
of how the entries will be ordered. Therefore the only reasonable
way to proceed is not to assume *anything* about how the entries
will be ordered.
Of course, which would sort them alphabetically, or whatever you make
it do. In this case, I would prefer them to be sorted by
last-date-modified, and that's why I ask; if this is how they're
sorted by default, then there's no need for me to code it.

It's not sorted any way by default. If you want a specific ordering,
you're going to have to do it yourself.

Chris Mattern
 
T

Tassilo v. Parseval

Also sprach Walter Roberson:
:> Schwartzian Transform unless you don't mind exponential numbers of
:> stat()'s.

:Exponential?

For small exponents ;-)

perldoc on sort says that it used to use quicksort, worst case O(N**2),
and now uses a mergesort, worst case O(N * log N) unless you request
quicksort specifically.

Ah, well. Exponential would be something like O(2^n). I think you meant
to say quadratic instead.

Tassilo
 
B

Bart Lateur

Mike said:
Is there a method to this madness?

It is sorted in order of physical appearance in the on-disk directory
listing structure. So it's nothing you can really use.
 
W

Walter Roberson

:>Is there a method to this madness?

:It is sorted in order of physical appearance in the on-disk directory
:listing structure. So it's nothing you can really use.

No it isn't; on UNIX systems, it's sorted in the readdir() order,
which is free to skip back and forth through the physical entries.
For example, if the directory used a tree structure, the distance from
the physical beginning of the block might reflect the number of N-ary
decisions whereas readdir() order might thread the leaves of the tree.
 
J

Joe Smith

Mike said:
I knew that perldoc didn't say anything, I was just making an
assumption because my server lists all of the files alphabetically by
default when you telnet in.

Strictly speaking, it is not the server that lists the files.
It is one or more programs on the server that lists the files.
The `ls` and `dir` programs are documented to explictly
alphabetize unless told otherwise. Try `ls -f` to see files
listed in directory order.
-Joe
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top