user3164754
user3164754

Reputation: 215

Picking up files from a directory in perl

I have gone through a bunch of questions to find the best way to get the names of the files from a directory. However, I have a peculiar scenario and need some help.

The files in my direcotry are as follows

-rw-rw-r--   1 root 55000  53916 Apr 12  2013 Update_2013-04-12_02-17-55.txt
-rw-rw-r--   1 root 55000  53916 Apr 12  2013 UpdateCIMS_2013-04-12_03-20-30.txt
-rw-rw-r--   1 root 55000  53763 Apr 15  2013 UpdateCIMSFlag_2013-04-15_05-47-41.txt
-rw-rw-r--   1 root 55000  91981 Apr 23  2013 UserManagementService_2013-04-23_03-55-52.txt
-rw-rw-r--   1 root 55000  92076 Apr 23  2013 UserManagementService_2013-04-23_04-34-42.txt
-rw-rw-r--   1 root 55000  92086 Apr 23  2013 UserManagementService_2013-04-23_23-55-10.txt
-rw-rw-r--   1 root 55000  91971 Apr 24  2013 UserManagementService_2013-04-24_02-23-20.txt
-rw-rw-r--   1 root 55000  59441 Apr 24  2013 SecuredService_2013-04-24_02-29-08.txt
-rw-rw-r--   1 root 55000  42240 May 20  2013 UpdateCIMSFlag_2013-05-20_04-24-19.txt
-rw-rw-r--   1 root 55000  40547 May 20  2013 UpdateCIMSFlag_2013-05-20_05-31-29.txt
-rw-rw-r--   1 root 55000  42238 May 20  2013 UpdateCIMSFlag_2013-05-20_05-43-54.txt
-rw-rw-r--   1 root 55000  59493 May 21  2013 SecuredService_2013-05-21_04-25-32.txt
-rw-rw-r--   1 root 55000  88374 May 21  2013 RegistrationService_2013-05-21_23-55-33.txt
-rw-rw-r--   1 root 55000  88426 May 22  2013 RegistrationService_2013-05-22_00-20-04.txt
-rw-rw-r--   1 root 55000  60014 Jul 31 04:16 SecuredService_2013-07-31_04-16-56.txt
-rw-rw-r--   1 root 55000  91636 Sep  2 06:11 AdminServices_2013-09-02_06-11-17.txt
-rw-rw-r--   1 root 55000  91649 Sep  3 05:37 AdminServices_2013-09-03_05-37-54.txt
-rw-rw-r--   1 root 55000 133629 Sep  3 05:43 UserManagementService2_2013-09-03_05-43-56.txt
-rw-rw-r--   1 root 55000    556 Sep  9 08:26 Test_2013-09-09_08-26-23.txt
-rw-rw-r--   1 root 55000    556 Sep  9 08:37 Test_2013-09-09_08-37-20.txt
-rw-rw-r--   1 root 55000 133708 Sep 13 02:28 UserManagementService2_2013-09-13_02-28-49.txt
-rw-rw-r--   1 root 55000  60107 Sep 13 02:30 SecuredService_2013-09-13_02-30-43.txt
-rw-rw-r--   1 root 55000 133743 Sep 13 04:44 UserManagementService2_2013-09-13_04-44-29.txt
-rw-rw-r--   1 root 55000 100886 Sep 16 04:27 AdminServices_2013-09-16_04-27-33.txt
-rw-rw-r--   1 root 55000    556 Sep 20 06:40 Test_2013-09-20_06-40-16.txt
-rw-rw-r--   1 root 55000 110236 Nov 25 02:35 AdminServices_2013-11-25_02-35-37.txt
-rw-rw-r--   1 root 55000 142357 Dec 18 03:13 UserManagementService2_2013-12-18_03-13-20.txt

As you can see, i have similar files with different timestamps and different files. So i need the file names which are similar excluding the timestamp and the latest file from them. I want my end result to display the latest, unique filenames with the timestamp.

I am trying opendir but am not seeing any result.

#!/usr/bin/perl
use File::stat;
my $DIR = "/home/DIR";
opendir(my $DH, $DIR) or die "Error opening the dir";
my %files = map { $_ => (stat("$DIR/$_"))[9] } grep(! /^\.\.?$/, readdir($DH));
closedir($DH);
my @sorted_files = sort { $files{$b} <=> $files{$a} } (keys %files);
print $_;

Please help. The output I am expecting is

AdminServices_2013-11-25_02-35-37.txt
UserManagementService2_2013-12-18_03-13-20.txt
SecuredService_2013-09-13_02-30-43.txt
RegistrationService_2013-05-22_00-20-04.txt
etc...

Upvotes: 2

Views: 175

Answers (3)

mpapec
mpapec

Reputation: 50637

#!/usr/bin/perl
my $DIR = "/home/DIR";
opendir(my $DH, $DIR) or die $!;

my %files;
while (my $f = readdir($DH)) {
  next if $f =~ /^\.\.?$/;

  my ($key, $t) = split /_/, $f, 2;
  # @{ $files{$key} }{ "t","f" } = ($t, $f) 
  #   if !$files{$key} or $files{$key}{t} lt $t;
  my $h = $files{$key} ||= {};
  if (! %$h or $h->{t} lt $t) {
    $h->{t} = $t;
    $h->{f} = $f;
  }
}

print "$files{$_}{f}\n" for sort keys %files;

Upvotes: 0

user1126070
user1126070

Reputation: 5069

You could use glob:

my $filespec = "/tmp/test*";
my %files;
while (my $file = glob("$filespec") ){
    next if $file eq '.' or $file eq '..';
    next if ! -f $file;
    my $datestamp = (stat($file))[9]; 
    #remove timestamp   
    my $filename = $file;     
    $filename =~ s!_\d{4}-\d{2}-\d{2}_\d{4}-\d{4}-\d{4}\.\W{3}\z!!is;
if (! exists $files{$filename} || $files{$filename}<$datestamp){
    $files{$filename} = $datestamp;
    $files{$filename} = $datestamp;
}                
}
foreach my $key (sort { $files{$b} <=> $files{$a} } (keys %files)){
  print "$key\t$files{$key}\n";
}

Upvotes: 0

Charity Leschinski
Charity Leschinski

Reputation: 2906

For a start, opendir isn't the problem. You aren't using the print statement correctly.

foreach(@sorted_files)
{  print $_ . "\n";  }

That outputs the file names. This is only a start to get you some output. I didn't finish the problem.

Upvotes: 1

Related Questions