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:
delete the newest file from the list

 



tester_V
Novice

Nov 17, 2017, 10:51 PM

Post #1 of 17 (4768 views)
delete the newest file from the list Can't Post

Hi,
I'm scanning a directory, collecting logs from the Dir to a list, I called it Flow.txt. I'd like to delete the newest file from the list of logs.
The logs naming goes like this:
Rbck_flow_log.2017-10-01.1
Rbck_flow_log.2017-10-01.2
Rbck_flow_log.2017-10-01.3
Rbck_flow_log.2017-10-01.4
and so on...
the question is how I can sort the list I collected and remove the newest file from it?
The sort function does not work on the mixed alfanumeric naming.
@sorted = sort { $a <=> $b } @unsorted;

here is the code I got so far.
Thank you.
Tester-V

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


my $dirname = "C:/LogFiles-S/" ;
opendir(DH, $dirname);
my @files = readdir(DH);
closedir(DH);

my $list1 = "C:/Sixshot_logs/Flow.txt" ;
open (my $list1_fh,'>',$list1 ) or die "cannot open $list1 \n" ;


foreach my $file (@files)
{
next if($file =~ /^\.$/);
next if($file =~ /^\.\.$/);
if ($file =~/flow/gi)
{
my $wholepath = "$dirname$file" ;
print $list1_fh sort"$wholepath \n" ;

}

}

close $list1_fh ;



Laurent_R
Veteran / Moderator

Nov 18, 2017, 3:33 AM

Post #2 of 17 (4764 views)
Re: [tester_V] delete the newest file from the list [In reply to] Can't Post

Hi,

if you use this:

Code
@sorted = sort { $a cmp $b } @unsorted;

or simply this:

Code
@sorted = sort  @unsorted;

it will work with the data sample you've shown. But it will break when the last digit goes over 9.

If the last number reaches 10 and more, then you need to split the string into substrings and sort on the substrings one after the other.

One common way to do it is to use the so-called Schwartzian Transform: https://en.wikipedia.org/wiki/Schwartzian_transform.

No time now to give you an example with data looking like yours, but maybe you can give a try with the help of the link provided. Otherwise, I might come back later to give a full solution.


Laurent_R
Veteran / Moderator

Nov 18, 2017, 4:19 AM

Post #3 of 17 (4761 views)
Re: [tester_V] delete the newest file from the list [In reply to] Can't Post

OK, now I've found the time.

This is a possible implementation of the Schwartzian transform for your data:


Code
use strict; 
use warnings;
use feature "say";

my @files = qw /
Rbck_flow_log.2017-10-01.1
Rbck_flow_log.2017-10-01.2
Rbck_flow_log.2017-10-01.13
Rbck_flow_log.2017-10-01.4
Rbck_flow_log.2017-10-01.10
Rbck_flow_log.2017-10-01.3
Rbck_flow_log.2017-10-01.12 /;

my @sorted = map { join ".", @$_ } # putting things back together
sort { $a->[1] cmp $b->[1] or $a->[2] <=> $b->[2]} # sorting on second and third fields
map { [split /\./, $_]} @files; # splitting input strings intio array refs
say for @sorted;


You should read the transform part (map ... sort ... map) from bottom to top: first split the strings into array refs, then sort, then put things back together.

And this prints out the following:

Code
Rbck_flow_log.2017-10-01.1 
Rbck_flow_log.2017-10-01.2
Rbck_flow_log.2017-10-01.3
Rbck_flow_log.2017-10-01.4
Rbck_flow_log.2017-10-01.10
Rbck_flow_log.2017-10-01.12
Rbck_flow_log.2017-10-01.13



(This post was edited by Laurent_R on Nov 18, 2017, 4:22 AM)


BillKSmith
Veteran

Nov 18, 2017, 7:56 AM

Post #4 of 17 (4755 views)
Re: [tester_V] delete the newest file from the list [In reply to] Can't Post

The Schwartzian Transform is a common idiom, but in this case, it is much easier to use the 'sort_by' function from the CPAN module List::UtilsBy. The documentation for 'sort_by' includes an example of naturally sorting strings that contain numbers.
Good Luck,
Bill


Laurent_R
Veteran / Moderator

Nov 18, 2017, 8:28 AM

Post #5 of 17 (4754 views)
Re: [BillKSmith] delete the newest file from the list [In reply to] Can't Post

The OP's problem involves a two- (or possibly three-) field sort, I fail to see how List::UtilsBy could handle that (at least from a quick look at its documentation).


tester_V
Novice

Nov 18, 2017, 12:49 PM

Post #6 of 17 (4746 views)
Re: [tester_V] delete the newest file from the list [In reply to] Can't Post

Thank you all for looking in to this problem!
It is really appreciated, I spent two days trying before asking for help.

I cannot install any modules on this PC it cannot access internet and it has Perl 5.8xxx

I tried to use Laurent_R code but it fails on line 3 for "use feature "say"; so I removed it.
I replaced "say" with print "@sorted \n " ; and the code really sorts the list.
It just prins everything on the same line and the " \n " did not work somehow.

I also wanted to remove the newest file from the list that was a major headache for me.
Thank you gain for looking in to it.
Tester_V


BillKSmith
Veteran

Nov 18, 2017, 2:00 PM

Post #7 of 17 (4741 views)
Re: [Laurent_R] delete the newest file from the list [In reply to] Can't Post

Laurent,

By following the example that I referenced, I get:

Code
use strict; 
use warnings;
use List::UtilsBy qw(sort_by);
my @files = qw /
Rbck_flow_log.2017-10-01.1
Rbck_flow_log.2017-10-01.2
Rbck_flow_log.2017-10-01.13
Rbck_flow_log.2017-10-01.4
Rbck_flow_log.2017-10-01.10
Rbck_flow_log.2017-10-01.3
Rbck_flow_log.2017-10-01.12 /;

my @sorted = sort_by { s/(\d+)$/sprintf "%03d", $1/er} @files;

{
local $" = "\n";
print "@sorted\n"
}


OUTPUT:
Rbck_flow_log.2017-10-01.1
Rbck_flow_log.2017-10-01.2
Rbck_flow_log.2017-10-01.3
Rbck_flow_log.2017-10-01.4
Rbck_flow_log.2017-10-01.10
Rbck_flow_log.2017-10-01.12
Rbck_flow_log.2017-10-01.13


Now that I have seen the actual code for each approach, I concede that the Schwartzian Transform is probably better. Even necessary given that the OP does not have access to the module.
Good Luck,
Bill


tester_V
Novice

Nov 18, 2017, 2:40 PM

Post #8 of 17 (4740 views)
Re: [tester_V] delete the newest file from the list [In reply to] Can't Post

Excellent!

I really appreciate your help!

As I said I cannot install any modules on the PC so "use List::UtilsBy qw(sort_by); " is out of the question.
The code works great if it is used with this input:

my @files = qw /
Rbck_flow_log.2017-10-01.1
Rbck_flow_log.2017-10-01.2
Rbck_flow_log.2017-10-01.13
Rbck_flow_log.2017-10-01.4
Rbck_flow_log.2017-10-01.10
Rbck_flow_log.2017-10-01.3
Rbck_flow_log.2017-10-01.12 /;

but if the lines are inside the "Flow.txt" file then the code sorts the lines but produces 2 types of error:

Unsuccessful stat on filename containing newline at...
Use of uninitialized value in numeric comparison (<=>) at C:....

It also does not remove the newest file from the list.

Thanks for trying!

Here your code modified little bit my me:

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

my $filename = "C:/Sixshot_logs/Flow.txt" ;
open (my $filename_fh, '<', $filename) or die $!;

my @file_list = <$filename_fh>;
# print " @file_list \n" ;
close $filename_fh;

my @file_modify_times = map { [ $_, (stat($_))[8] ] } @file_list;
my @files_sorted_by_mtime = sort { $a->[1] <=> $b->[1] } @file_modify_times;
#print "@files_sorted_by_mtime \n" ;
my @sorted_files = map { $_->[0] } @files_sorted_by_mtime;
print "@sorted_files \n" ;


Code
 


Thank you again for your help!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Forgot one thing.
The list of logs have extensions ".log"
So it is:
Rbck_flow_log.2017-10-01.1.log
Rbck_flow_log.2017-10-01.2.log
Rbck_flow_log.2017-10-01.13.log
Rbck_flow_log.2017-10-01.4.log
Rbck_flow_log.2017-10-01.10.log
Rbck_flow_log.2017-10-01.3.log
Rbck_flow_log.2017-10-01.12.log

Not :

Rbck_flow_log.2017-10-01.1
Rbck_flow_log.2017-10-01.2
Rbck_flow_log.2017-10-01.13
Rbck_flow_log.2017-10-01.4
Rbck_flow_log.2017-10-01.10
Rbck_flow_log.2017-10-01.3
Rbck_flow_log.2017-10-01.12

Code


	

(This post was edited by tester_V on Nov 18, 2017, 3:03 PM)


Laurent_R
Veteran / Moderator

Nov 18, 2017, 3:01 PM

Post #9 of 17 (4738 views)
Re: [tester_V] delete the newest file from the list [In reply to] Can't Post


In Reply To
I tried to use Laurent_R code but it fails on line 3 for "use feature "say"; so I removed it.
I replaced "say" with print "@sorted \n " ; and the code really sorts the list.
It just prins everything on the same line and the " \n " did not work somehow.


Yeah, I did not know you were stuck with such an old version of Perl. "say" was introduced with version 5.10 (which came out in 2009).

Try this:

Code
print "$_\n" for @sorted;




In Reply To
I also wanted to remove the newest file from the list that was a major headache for me.

The pop function, used on the @sorted array, will return the last item of the array (newest file) and remove it from the array.

Update: you completely changed your post after I responded to it. My answers now look weird and unrelated to your post.

Update 2: Oh, no, it is actually a new post that you posted. Sorry, our posts sort of crossed each other.


(This post was edited by Laurent_R on Nov 18, 2017, 3:23 PM)


Laurent_R
Veteran / Moderator

Nov 18, 2017, 3:06 PM

Post #10 of 17 (4736 views)
Re: [BillKSmith] delete the newest file from the list [In reply to] Can't Post

Yes, Bill, I agree that with the simple data example I posted, sort_by would probably work. But my point is that it would probably not with an example where the date within the file names would also change.


tester_V
Novice

Nov 18, 2017, 3:11 PM

Post #11 of 17 (4734 views)
Re: [Laurent_R] delete the newest file from the list [In reply to] Can't Post

Thanks man! I really do not understand the MAP function, I see it is powerful. What does this part of the code mean (stat($_))[8]? I'm trying to "Google" it but nothing useful or understandable found so far.

Code
 
Thank you for your time again!


Laurent_R
Veteran / Moderator

Nov 18, 2017, 3:19 PM

Post #12 of 17 (4732 views)
Re: [tester_V] delete the newest file from the list [In reply to] Can't Post

the stat function returns a 13-element list with file information on its argument. The ninth element (item with subscript 8) is the last access date to the file. This may be what you need, but it is probably not, watch out that the last time the file was accessed is definitely not the same thing as the order in which the files were produced. Many events may modify the last access date after the file was produced, so that your code may not pick up the most recent file.


Laurent_R
Veteran / Moderator

Nov 18, 2017, 3:28 PM

Post #13 of 17 (4730 views)
Re: [tester_V] delete the newest file from the list [In reply to] Can't Post


In Reply To
The code works great if it is used with this input:

my @files = qw /
Rbck_flow_log.2017-10-01.1
Rbck_flow_log.2017-10-01.2
Rbck_flow_log.2017-10-01.13
Rbck_flow_log.2017-10-01.4
Rbck_flow_log.2017-10-01.10
Rbck_flow_log.2017-10-01.3
Rbck_flow_log.2017-10-01.12 /;

but if the lines are inside the "Flow.txt" file then the code sorts the lines but produces 2 types of error:

Unsuccessful stat on filename containing newline at...
Use of uninitialized value in numeric comparison (<=>) at C:....

If you're reading your filenames from a file, then you need to use chomp to remove the trailing newline character from the input before you use stat on them.

But, as I said before, I doubt it is a good idea to use stat for your purpose.

BTW, where did you get the idea of using stat from? From your other question, it seems you don't understand what it does.

Did you post on another forum?



(This post was edited by Laurent_R on Nov 18, 2017, 3:31 PM)


tester_V
Novice

Nov 18, 2017, 11:08 PM

Post #14 of 17 (4721 views)
Re: [Laurent_R] delete the newest file from the list [In reply to] Can't Post

The idea about stats I got from the code you guys posted above.
And yes, I have no idea what it does.

Thank you got you help.


tester_V
Novice

Nov 19, 2017, 10:27 AM

Post #15 of 17 (4715 views)
Re: [tester_V] delete the newest file from the list [In reply to] Can't Post

Should I post this somewhere else?
So far I have enough help here.

Just wondering, why I should post it in other forums?

Thank you.


Laurent_R
Veteran / Moderator

Nov 19, 2017, 1:56 PM

Post #16 of 17 (4710 views)
Re: [tester_V] delete the newest file from the list [In reply to] Can't Post

No, no, you got me wrong or perhaps I wasn't clear enough. I was just asking whether you had posted somewhere else, because you used stat in your code but did not seem to know what it does, so I thought that maybe someone on another forum suggested to use stat.

But I wasn't suggesting that you should post on other forums. I think that people here are willing to help you at least as much as in any other forum that I know.


tester_V
Novice

Nov 19, 2017, 2:30 PM

Post #17 of 17 (4708 views)
Re: [Laurent_R] delete the newest file from the list [In reply to] Can't Post

I think you guys great!

Thank you again.
Special thanks to Laurent.Cool

 
 


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

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