sorting file names

M

mixo

I have file name that have a prefix "t-", which
is followed by a number (integer), like
t-1
t-2
t-3
t-10
t-21
and so on.

How can I sort this in numeric order? This avoid a situation
where I get:
t-1
t-10
t-2
t-21
t-3
and so on.

So I far have the following which suffers from the above symptom:
++++++++++++
#!/usr/bin/perl -w
opendir THISDIR, "." or die "serious dainbramage: $!";
@allfiles = readdir THISDIR;
@allfiles = sort @allfiles;
#@allfiles = reverse @allfiles;


closedir THISDIR;
print "@allfiles\n";
++++++++++++
 
W

W K

But im almost 100% sure there are others here who can
give you more elegant solutions.

I don't usually like to play about with "elegant" and "map" as some C
programmer might have to look at it.
Anyway:

@a=qw(t-1 t-12 t-4 t-50 t-24);
print join("\n",sort {substr($a,2)<=>substr($b,2)} @a);

Moral of the story : you can muck about with what is in the sort {block}
 
I

Ingo Menger

@allfiles = sort @allfiles;

@allfiles = map { "t-$_" }
sort { $a <=> $b }
map { s/^t-// } @allfiles;

In english:
Assign to @allfiles the array that results from
prepending the string "t-" to each element of the array
that results from a numeric sort of the array
that results from stripping the string "t-" from each element of @allfiles
#@allfiles = reverse @allfiles;

To reverse the sort, swap $a and $b in the sort sub.
 
A

Anno Siegel

Ingo Menger said:
@allfiles = map { "t-$_" }
sort { $a <=> $b }
map { s/^t-// } @allfiles;

Untested, eh?

You forgot that s/// returns success or failure of the replacement, not
the changed string. Change the last line to

map { s/^t-//; $_ } @allfiles;

Anno
 
J

Jeff 'japhy' Pinyan

You forgot that s/// returns success or failure of the replacement, not
the changed string. Change the last line to

map { s/^t-//; $_ } @allfiles;

I'd use grep(). It saves the effort of having to return $_, and it makes
more sense because this code is designed to sort those SPECIFIC files:

@allfiles =
map "t-$_",
sort { $a <=> $b }
grep s/^t-//,
@allfiles;
 
S

Sara

mixo said:
I have file name that have a prefix "t-", which
is followed by a number (integer), like
t-1
t-2
t-3
t-10
t-21
and so on.

How can I sort this in numeric order? This avoid a situation
where I get:
t-1
t-10
t-2
t-21
t-3
and so on.

So I far have the following which suffers from the above symptom:
++++++++++++
#!/usr/bin/perl -w
opendir THISDIR, "." or die "serious dainbramage: $!";
@allfiles = readdir THISDIR;
@allfiles = sort @allfiles;
#@allfiles = reverse @allfiles;


closedir THISDIR;
print "@allfiles\n";
++++++++++++


The statement

@allfiles = sort @allfiles;

is NOT a numeric sort. It's an alphanumeric sort. You'll need to use
the spaceship operator to do a numeric sort <=> . However you don't
have numbers..

Since you APPEAR to have a constant 'T-' in front of the filenames,
lets strip that off, sort numerically, then put it back. If its not a
true constant, you will have to store the prefix then put it back.

OK lets get busy. Remember, loops like for {} BAD! Let's use some Perl
instead:

#!/usr/bin/perl -wd

my @a = qw(T-1 T-12 T-5 T-3 T-6);
map s/^\D+//,@a; # stip off the prefix, don't really need the carat
but its OK
@a = sort { $a <=> $b } @a; # sort numerically using spaceship
map s/^/T-/,@a; # put the prefix back on
print "$_\n" for @a; # report success!


DB<1> c
T-1
T-3
T-5
T-6
T-12
Debugged program terminated. Use q to quit or R to restart,

Happy Holidays.
G
 
J

Jürgen Exner

mixo said:
I have file name that have a prefix "t-", which
is followed by a number (integer), like
t-1
t-2
t-3
t-10
t-21
and so on.

How can I sort this in numeric order?

Oh come on, it's not that difficult.
++++++++++++
#!/usr/bin/perl -w
opendir THISDIR, "." or die "serious dainbramage: $!";
@allfiles = readdir THISDIR;
@allfiles = sort @allfiles;

Did you read the documentation of sort()?
It clearly says:
[...]. If SUBNAME or
BLOCK is omitted, "sort"s in standard string comparison order.

And further down in the examples:
# sort numerically ascending
@articles = sort {$a <=> $b} @files;

Now, obviously your file names are not numbers, so the code block needs to
extract the number part of $a and $b before calling <=>. Because you have
such a well-defined format you could simply use substr to remove the
unwanted "t-":

sort {substr($a said:
closedir THISDIR;
print "@allfiles\n";
++++++++++++

jue
 
D

David

mixo said:
How can I sort this in numeric order? This avoid a situation
where I get:
t-1
t-10
t-2
t-21
t-3
and so on.

Sounds like a job for Sort::Naturally, available at your local CPAN mirror.

- David
 
J

James E Keenan

mixo said:
I have file name that have a prefix "t-", which
is followed by a number (integer), like
t-1
t-2
t-3
t-10
t-21
and so on.

How can I sort this in numeric order? This avoid a situation
where I get:
t-1
t-10
t-2
t-21
t-3
and so on.

So I far have the following which suffers from the above symptom:
++++++++++++
#!/usr/bin/perl -w
opendir THISDIR, "." or die "serious dainbramage: $!";
@allfiles = readdir THISDIR;
@allfiles = sort @allfiles;
#@allfiles = reverse @allfiles;


closedir THISDIR;
print "@allfiles\n";
++++++++++++

my @list = qw(t-1
t-2
t-3
t-10
t-21);

my (@files);
push (@files, (split/-/, $_)[1]) for (@list);

for (sort {$a <=> $b } @files) {
print "t-$_\n";
# do appropriate processing
}

HTH

jimk
 
C

Chris Charley

mixo said:
I have file name that have a prefix "t-", which
is followed by a number (integer), like
t-1
t-2
t-3
t-10
t-21
and so on.

How can I sort this in numeric order?

You could use the Schwartzian Transform. It is easier to follow if you
read from the end of the expression (because this is the order of
execution).
Note that each file name, and the digits to sort on are placed in an
anonymous array in the bottom map which is then passed to the sort
line, and so forth.

Chris

#!/usr/bin/perl
use strict;
use warnings;

my @files = qw / t-1.txt t-4.txt t-10.txt t-14.txt t-11.txt /;

my @sorted = map {$_->[0]}
sort {$a->[1] <=> $b->[1]}
map { [ $_, /-(\d+)/ ] }
@files;

print "@sorted\n";

__END__
output: t-1.txt t-4.txt t-10.txt t-11.txt t-14.txt
 
I

Ingo Menger

Untested, eh?

Sure. There has to be something left as execise for the OP. :)

map { s/^t-//; $_ } @allfiles;

or, better yet:

map { substr($_, 2) } @allfiles

or
map { m/^t-(\d+)/ and $1 } @allfiles

It's preferrable not to change lvalues if you don't have to.
 

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,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top