-2

I'm creating a script where I need to get the Last Modified Date of the files I checked this thread How do I get a file's last modified time in Perl?

So I used the script below to get the last modified, at first it was working but when I try to run it again, the timestamp returns 00:00 January 1, 1970.

Why is that happening and how can I get the correct last modified date and time?

my $dir = '/tmp';
    
opendir(DIR, $dir) or die $!;
@content=readdir(DIR);

foreach(@content)
{
    next unless ($_ =~ m/\bfile.txt|file2.csv\b/);

    my $epoch_timestamp = (stat($_))[9];
    my $timestamp       = localtime($epoch_timestamp);
    $f_detail = $_ .' '.$timestamp;
    print "$f_detail\n";
}
closedir(DIR);
    
exit 0;

When I tried to run the perl, I will get this result

  • file.txt Thu Jan 1 00:00:00 1970

  • file2.csv Thu Jan 1 00:00:00 1970

Ok, last update, it is working now, I try to run all of the scripts you've given to me, standalone script. I found what's causing the default time, see the script below, I remove that in my program and it works, didn't notice this at first, sorry. But still, it feels weird because I was sure that it is working when I first run it, but now it is working so yeah thank you guys!

if (($month = ((localtime)[4] + 1)) < 10)
{
  $month = '0' . $month;
}
if (($day = ((localtime)[3])) < 10)
{
  $day = '0' . $day;
}
if (($year = ((localtime)[5]+1900)) >= 2000)
{

  if (($year = $year - 2000) < 10)
  {
    $year = '0' . $year;
  }
}
else
{
  $year = $year - 1900;
}

$date = $month . $day . $year;
joanis
  • 10,635
  • 14
  • 30
  • 40
Ekwita
  • 21
  • 7
  • 1
    Do you have [warnings](http://p3rl.org/warnings) on? Getting the start of epoch usually means the file doesn't exist or insufficient permissions to stat it. – choroba Feb 08 '22 at 13:19
  • oh sorry! I updated the script, yes the file exists. it's kinda weird because it was working at first run but when I tried to rerun it, the default returns – Ekwita Feb 08 '22 at 13:40
  • 2
    If you're only interested in two files you know ahead of time, you don't need opendir/readdir... – Shawn Feb 08 '22 at 14:26
  • I just put two files, but in my current code I'm checking 6 files and soon I need to check more than 6 files – Ekwita Feb 08 '22 at 14:34
  • 1
    Unrelated bug: `/\bfile.txt|file2.csv\b/` should be `/\b(?:file\.txt|file2\.csv)\b/` at a minumum, but `/^(?:file\.txt|file2\.csv)\z/` is probably what you want. – ikegami Feb 08 '22 at 16:28

3 Answers3

4

readdir returns file names without the full path. You need to prepend the path manually:

for (@content) {
    next unless /^(?:file\.txt|file2\.csv)\z/;

    my $epoch_timestamp = (stat("$dir/$_"))[9];
    #                           ~~~~~~~~~

Also note how I changed the regex to match the file names.

ikegami
  • 367,544
  • 15
  • 269
  • 518
choroba
  • 231,213
  • 25
  • 204
  • 289
  • The time still the same :( thank you for the giving some tips about matching the file names it is much better, it gets the exact file names! :) – Ekwita Feb 08 '22 at 14:11
  • Add a test `-e "$dir/$_" or warn "$_ not found!";` or something similar. You can also check the readability with `-r`. – choroba Feb 08 '22 at 16:18
  • it is now working! thank you! – Ekwita Feb 09 '22 at 06:21
2

If you have a directory name, and you want to see if some files whose names you already know exist in that directory, there's really no need for opendir/readdir - that's more helpful if you don't know the filenames ahead of time. When you do, you can just build a path using both parts and use file test operators/stat/etc. on it.

#!/usr/bin/env perl
use strict;
use warnings;
use feature qw/say/;

my $dir = '/tmp';
my @files = qw/file.txt file2.csv/;

for my $file (@files) {
    # Better to use File::Spec->catfile($dir, $file), but your question
    # title said no modules...
    my $name = "$dir/$file";
    if (-e $name) { # Does the file exist?
        # _ to re-use the results of the above file test operator's stat call
        my $epoch_timestamp = (stat _)[9]; 
        my $timestamp       = localtime $epoch_timestamp;
        say "$file $timestamp";
    }
}

Example execution:

$ perl demo.pl
file.txt Tue Feb  8 07:26:07 2022
file2.csv Tue Feb  8 07:26:10 2022
Shawn
  • 47,241
  • 3
  • 26
  • 60
1

Following demo code utilizes glob to obtain modification time for specified files in a directory.

use strict;
use warnings;
use feature 'say';

my $dir   = '/tmp';
my @files = qw(file.txt file2.csv);
my $mask  = join ' ',  map { "$dir/$_" } @files;

say "$_\t" . localtime((stat($_))[9]) for glob($mask);
Polar Bear
  • 6,762
  • 1
  • 5
  • 12