CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
Readdir & sort

 



Pro_4
User

Jul 1, 2001, 2:13 PM

Post #1 of 22 (4782 views)
Readdir & sort Can't Post

Hey,

How should i go about reading in a directory and then displaying the directory contents according to the most current and then going down to the oldest.

Thanks i really appreciate it.

Yes i am a palm tree. What are you plantist or something!?


mhx
Enthusiast / Moderator

Jul 1, 2001, 2:33 PM

Post #2 of 22 (4781 views)
Re: Readdir & sort [In reply to] Can't Post

Hi Pro_4,

the following code will read a directory $dir and display its contents sorted by the last modification date (which is the actually the index 9 of the array returned by stat).

Code
my $dir = '/my/directory'; 

opendir DIR, $dir or die "cannot open '$dir': $!\n";
my @files = map $_->[0],
sort { $b->[1] <=> $a->[1] }
map [$_, (stat)[9]],
readdir DIR;
closedir DIR;

print join "\n", @files;

Hope this helps.

-- Marcus



Pro_4
User

Jul 1, 2001, 5:39 PM

Post #3 of 22 (4777 views)
Re: Readdir & sort [In reply to] Can't Post

Wow, thanks mhx, but a little explaination or a link to stuff on that would be helpful to just in case i need to modify that.

Yes i am a palm tree. What are you plantist or something!?


Jasmine
Administrator / Moderator

Jul 1, 2001, 8:16 PM

Post #4 of 22 (4774 views)
Re: Readdir & sort [In reply to] Can't Post

Pro_4,

If you're referring to the map/sort/map thing, that's the Schwartzian Transform. You can see my explanation for it at http://forums.perlguru.com/showflat.pl?Board=Forum2&Number=10992#Post10992



mhx
Enthusiast / Moderator

Jul 1, 2001, 9:33 PM

Post #5 of 22 (4771 views)
Re: Readdir & sort [In reply to] Can't Post

I just figured out another page that has even some pictures to explain the Schwartzian Transform in detail. It also tells you why it so special (because it speeds up searching). They do almost the same thing as you wanted, except they sort files by size in that article.

-- Marcus



Pro_4
User

Jul 2, 2001, 7:29 AM

Post #6 of 22 (4767 views)
Re: Readdir & sort [In reply to] Can't Post

Thanks a lot, when i read that you have to read it from the bottom to the top to understand it, things just clicked for me. Anyways why does perl read that part from bottom to top or am i miss understanding something about how perl interprets you code.

--- So what version of the Internet do you have? I have version 3.02, it took me three months to download it.


Pro_4
User

Jul 2, 2001, 8:34 AM

Post #7 of 22 (4764 views)
Re: Readdir & sort [In reply to] Can't Post

Hmm, well it seems to be working but the thing is how do i use that information that was sorted, like how do i print that in the order that it sorted. When i ran that code all it showed was a blank screen. ( i added the print header; so something would be able to show on the webpage).

Also i noticed to different styles of joining the information. Jasmine did this:

map { join ' -- ', @$_ }

and Mhx did this:

print join "\n", @files;

Is there any advantage of one way over the other way. And by join i assumed that made the data look like this:

File1|file2|file3|file4

And based on that assumption i attempted to split @files by the | and print out all the results but gave me nothing. What am i doing wrong?


--- So what version of the Internet do you have? I have version 3.02, it took me three months to download it.


mhx
Enthusiast / Moderator

Jul 2, 2001, 10:43 AM

Post #8 of 22 (4758 views)
Re: Readdir & sort [In reply to] Can't Post

Hi,


In Reply To
Hmm, well it seems to be working but the thing is how do i use that information that was sorted, like how do i print that in the order that it sorted. When i ran that code all it showed was a blank screen. ( i added the print header; so something would be able to show on the webpage).

Have you tried running the script from the command line? Have you set $dir to an existing directory? I've tried the script before I posted it, and on my terminal I received the file names in order from new to old (worked with both Win and Unix).

In Reply To
Also i noticed to different styles of joining the information. Jasmine did this:
map { join ' -- ', @$_ }
and Mhx did this:
print join "\n", @files;
Is there any advantage of one way over the other way.

As always in Perl, there's more than one way to do it. But in this case, you mixed up different things. While Jasmine's map { join ... } joined the contents of a two-dimensional array by putting ' -- ' between the elements in each row, my join simply added newline characters between the @files, so they appear each on a new line. Another (perhaps more convenient way) of doing this would be to redefine the list separator $":

Code
$" = "\n"; 
print "@files\n";

This will, when interpolating the @files array in the string, insert the $", which I redefined to be a newline character, between all elements of the @files array. So the result is the same, whether you use $" or join. But don't ask me which of them is better ;-)

In Reply To
And by join i assumed that made the data look like this:
File1|file2|file3|file4

No, because I've joined with a newline. It would look like this:

Code
file1 
file2
file3
file4


In Reply To
And based on that assumption i attempted to split @files by the | and print out all the results but gave me nothing. What am i doing wrong?

Don't try to split the @files again, because each element of @files is yet a single file that shoudn't be splitted anymore.
The only hint I can give you just now is to try to get the script working on the command line first. This should be no big deal, because it should work immediately. If you got it running, try to port it to CGI.
If you have any other specific questions to the script, feel free to ask.

-- Marcus



rGeoffrey
User / Moderator

Jul 2, 2001, 11:42 AM

Post #9 of 22 (4754 views)
Re: Readdir & sort [In reply to] Can't Post

I did a search through the old threads looking for 'Schwartzian" to find several threads where a Schwartzian Transform was explained or used. Also included are links to some outside pages that also explain it.

The link for "A Fresh Look at Efficient Perl Sorting" is to Uri's site because the link from perlfaq.com was to Larry's copy which has gone missing. This paper won a prize at The Perl Conference 3.0 (1999).

Other places with an explanation of a Schwartzian or Guttman-Rosler Transform

More about the Schwartzian Transform by Joseph N. Hall
What are the Schwartzian and Guttman-Rosler Transforms? by Greg Bacon
The Perl Hardware Store by Mark-Jason Dominus
A Fresh Look at Efficient Perl Sorting by Uri Guttman and Larry Rosler

Threads with an explanation of a Schwartzian Transform

Sorting how ? by Jasmine
Map??? by rGeoffrey
sort and print by rGeoffrey
Sort flat database by rGeoffrey
How do I write SORT routine by japhy
Sorting a hash? by japhy
sorting array by Kanji

Threads with an example of a Schwartzian Transform

Easy One: Sort Question by japhy
sorting problem by Kanji and rGeoffrey
How do I sort an array by (anything)? by Jasmine
Sorting an array ! by dws

PS. The order that threads are listed is random based on the the order that I looked at them and not the order of usefulness or age.


--
Sun Sep 9, 2001 - 1:46:40 GMT, a very special second in the epoch. How will you celebrate?


Pro_4
User

Jul 2, 2001, 5:54 PM

Post #10 of 22 (4722 views)
Re: Readdir & sort [In reply to] Can't Post

Thanks Geoffrey. Mhx, i got it to work on the command prompt no problem. One interesting thing i noticed was when i left the $dir empty it did the contents of c:/ not the contents of the folder that the script was in. So i was wondering if that could be my problem with the cgi script. Do i need the full path to the directory i want to sort?

Also say i just wanted to print the first ten most recent files. I tried the

my @data = map [split /\|/], @files;

Then i realized how stupid that was because those files are not seperated by | in the @files. So i was wondering how do i make it so i can use that
print $file[0][1];
to print the top 10 most recently modified.

Thanks :)

--- So what version of the Internet do you have? I have version 3.02, it took me three months to download it.


mhx
Enthusiast / Moderator

Jul 2, 2001, 10:03 PM

Post #11 of 22 (4715 views)
Re: Readdir & sort [In reply to] Can't Post


In Reply To
One interesting thing i noticed was when i left the $dir empty it did the contents of c:/ not the contents of the folder that the script was in. So i was wondering if that could be my problem with the cgi script. Do i need the full path to the directory i want to sort?

No, a relative path will be sufficient. If you want the contents of the current directory, just say

Code
my $dir = '.';


In Reply To
Also say i just wanted to print the first ten most recent files.

To print only the 'top ten', use an array slice. I've reprinted the whole code here:

Code
#!/bin/perl -w 
use strict;

my $dir = '.'; # current directory

opendir DIR, $dir or die "cannot open '$dir': $!\n";
my @files = map "$_->[0]\n",
sort { $b->[1] <=> $a->[1] }
map [$_, (stat)[9]],
readdir DIR;
closedir DIR;

print @files[0..9]; # print elements 0 to 9 (top ten)

Also, I've found a third way of getting the newline sequence in. I've put it into the already existing map, so the print statement looks a bit nicer and it saves you an addition join.
With an array slice, you can cut elements out of an array by their index. Array slices are not limited to ranges, you can specify arbitrary indices in the square brackets. You could even use another array that would hold indices for an array slice. For example,

Code
my @a = ('A'..'Z', ' '); 
my @i = (15, 4, 17, 11);

print @a[@i,-1,7,0,2,10,@i[1..2]];

will print "PERL HACKER". You can try to find out why it prints this. If you got this, you will definetely know how array slices work. As you can see, in the slice I'm using an array (@i), some arbitrary indices (including -1, which refers to the last index) and even another array slice (@i[1..2]). There are also hash slices, and they work in quite the same way:

Code
my %t = ( 
sec => 42,
min => 5,
hour => 7,
day => 3,
month => 7,
year => 2000,
);

print "It's ", join '-', @t{year,month,day};

You could even use this to print the hash values sorted by the keys of the hash:

Code
print "@t{sort keys %t}";

I hope this helps and makes the slicing technique a bit clearer.

-- Marcus



Pro_4
User

Jul 3, 2001, 8:38 AM

Post #12 of 22 (4710 views)
Re: Readdir & sort [In reply to] Can't Post

wow that perl hacker stuff is cool and the good thing about it is that i understand it (i believe) If i understood it right it was just useing that array (@i) to find certain letters that were contained in @a. For example if i wanted to print Pro_4 i would do this:
@letters = ('A'..'Z', 'a'..'z', '1'..'5', '_');
@i = ( '15', '43', '40');
print @letters [ @i, -1, 55];

Haha that is cool, i am going to make that my new signiture for my posts. Thanks mhx again for all the help!

--- So what version of the Internet do you have? I have version 3.02, it took me three months to download it.


mhx
Enthusiast / Moderator

Jul 3, 2001, 9:05 AM

Post #13 of 22 (4709 views)
Re: Readdir & sort [In reply to] Can't Post

Cool, I think you've got it!


Code
s~~join'',map chr,(unpack'C*','Pro_4!')[0,2,1,3..5]~e and tr/0-9!D-Z_o-q/q-zsA-Wca-c/ and print



Pro_4
User

Jul 3, 2001, 10:13 AM

Post #14 of 22 (4707 views)
Re: Readdir & sort [In reply to] Can't Post

cool that prints your name... what is my name doing in there, is it translating certain letters in my name and making yours?

@letters = ('A'..'Z', 'a'..'z', '1'..'5', '_');
@i = ( '15', '43', '40');
print @letters [ @i, -1, 55];


mhx
Enthusiast / Moderator

Jul 3, 2001, 10:19 AM

Post #15 of 22 (4705 views)
Re: Readdir & sort [In reply to] Can't Post

Yes, that's what it's all about. I recognized your name translates to mine quite easily ;-)

-- Marcus ( who doesn't want to figure out another way of tr/ Pro_4 / Marcus / )



Pro_4
User

Jul 3, 2001, 3:04 PM

Post #16 of 22 (4697 views)
Re: Readdir & sort [In reply to] Can't Post

hmm, i am trying to do Jasmines way of reading a file and sorting according to a number in the database. But as usual things dont like working for me. I used the exact same code she did and it still didnt work, so i am assuming that there must be something different i did in the way of printing out the info @newarray.

Code
#!/usr/bin/perl -w 
open (DATA, "+>> posts.txt") || die $!;
my @newarray = map { join ' -- ', @$_ }
sort { $a->[1] <=> $b->[1] }
map { [ split /\|/ ] }
<DATA>;
print @newarray[0..9];
close(DATA);

Also i was wondering what are the numbers that (stat)[9] would print out. I have tried print (stat)[9]; but that gave me a lot of number that never changed when i tried it over and over again. Thanks :)


@letters = ('A'..'Z', 'a'..'z', '1'..'5', '_');
@i = ( '15', '43', '40');
print @letters [ @i, -1, 55];


mhx
Enthusiast / Moderator

Jul 3, 2001, 11:57 PM

Post #17 of 22 (4689 views)
Re: Readdir & sort [In reply to] Can't Post

Hi,

If your posts.txt file that looks like this

Code
Hello|1|bagkgm|fklme 
World|4|ewlkngal
Test|2|dngjna|mrelkg
Marcus|0|kewgl|fwnelng|gran
Perl|10|dgkjmj
Larry|8|mlkagmnlk
Wall|666|kdgslak
Don't|13|dslkgg
Have|123|dglsmg
More|29|dglkajh
Ideas|23|fsdgk

the script you posted will print

Code
Marcus -- 0 -- kewgl -- fwnelng -- gran 
Hello -- 1 -- bagkgm -- fklme
Test -- 2 -- dngjna -- mrelkg
World -- 4 -- ewlkngal
Larry -- 8 -- mlkagmnlk
Perl -- 10 -- dgkjmj
Don't -- 13 -- dslkgg
Ideas -- 23 -- fsdgk
More -- 29 -- dglkajh
Have -- 123 -- dglsmg

If this isn't what you expected, please tell me what you would expect...
Why do you open the file Read/Write/Append mode? If you want to append the data in @newarray to the original file (which doesn't make much sense to me), you have write

Code
print DATA @newarray[0..9];


In Reply To
Also i was wondering what are the numbers that (stat)[9] would print out.

The stat function return status info for a file. See perldoc -f stat for details. If called without arguments (as in your quote), it returns the info for the file stored in $_, which is probably why it didn't change. The [9] is just the 10th element of the list returned by stat, and that's the last modify time.

-- Marcus



Pro_4
User

Jul 4, 2001, 7:50 AM

Post #18 of 22 (4683 views)
Re: Readdir & sort [In reply to] Can't Post

Hm interesting. When i use +>> to take in the information to be sorted, the print @newarray[0..9]; doesnt print anything out. But when i use < to take in the information to sort it, the print works. Why does it do that?

@letters = ('A'..'Z', 'a'..'z', '1'..'5', '_');
@i = ( '15', '43', '40');
print @letters [ @i, -1, 55];


mhx
Enthusiast / Moderator

Jul 4, 2001, 9:58 AM

Post #19 of 22 (4680 views)
Re: Readdir & sort [In reply to] Can't Post

Hi,


In Reply To
When i use +>> to take in the information to be sorted, the print @newarray[0..9]; doesnt print anything out. But when i use < to take in the information to sort it, the print works. Why does it do that?

It seems we've now come to the platform dependencies of Perl! Let me guess, you're running Perl under Windows? I've actually tested the script under HP-UX, and it does what I described and you probably expected. I really don't know the reason why it doesn't work under Windows. Unless anyone else has a better idea, I'd first open the file for reading, read in the data, close the file, open it again for appending, and print the data to the file.

-- Marcus



Pro_4
User

Jul 4, 2001, 11:08 AM

Post #20 of 22 (4678 views)
Re: Readdir & sort [In reply to] Can't Post

Thanks now i figured out a problem that has been troubling me forever. Now for some reason all memory of how to split has just lost me. How do you double split something.

My database is setup like this:
Pro_4|test|Date+!+Pro_4|Testagain|Date

I want to split by the +!+ (this is going to be used for a forum so the +!+ seperates the replies), then after i split by the +!+ i want to split it again with the |.

So if i did print $data[0][0]; it would print Pro_4 and if i did print $data[1][1] it would print Testagain.

It is right on the tip of my tongue but i cant figure it out! It is buggin me.

@letters = ('A'..'Z', 'a'..'z', '1'..'5', '_');
@i = ( '15', '43', '40');
print @letters [ @i, -1, 55];


mhx
Enthusiast / Moderator

Jul 4, 2001, 1:11 PM

Post #21 of 22 (4676 views)
Re: Readdir & sort [In reply to] Can't Post

Hi Pro_4,

that split is quite easy. Assume you're reading from FILE, this would be

Code
my @data = map [split /\|/], split /\+!\+/, <FILE>;

Hope your memory's back now... ;-)

-- Marcus



Pro_4
User

Jul 4, 2001, 8:14 PM

Post #22 of 22 (4674 views)
Re: Readdir & sort [In reply to] Can't Post

Thanks, now i remember. ( I think that rock my brother threw at me did more than hurt Smile )

Thanks again

BTW if you want to see what i am working on check out here

@letters = ('A'..'Z', 'a'..'z', '1'..'5', '_');
@i = ( '15', '43', '40');
print @letters [ @i, -1, 55];

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives