Hans Fong
Hans Fong

Reputation: 1

Perl: can't get time stamps from files in directory --> Use of uninitialized value in line 18

My goal: list the *gz files in a directory with name and creation date.

I wrote the following

#!/usr/bin/perl
use strict;
use warnings;
use File::stat;
use Time::localtime;

my $directory = '/home/hans/.config/cqrlog/database';
opendir (DIR, $directory) or die $!;
my @files = (readdir(DIR));
closedir(DIR);

foreach $_ (@files) {
    # Use a regular expression to find files ending with .gz
    if ($_ =~ m/\.gz$/) {
        my $file_name = $_;
        my $file_time = (stat($_))[9];
        print "$file_time\n";
    }
}

But I do keep getting the often seen error "Use of uninitialized value $file_time in concatenation (.) or string at ./perl-matching-files.pl line 18." which is the print line.

I also tried the following:

foreach $_ (@files) {
    # Use a regular expression to find files ending with .gz
    if ($_ =~ m/\.gz$/) {
        my $file_name = $_;
        my @file_time_array = (stat($_));
        my $file_time = $file_time_array[9];
        print $file_name , " - " , $file_time , "\n";
    }
}

But again it barfs at the last print line. I also tried a while-loop, but wit the same results. The file names are printed out, though, so I must be doing something right. I feel that when reading through the array the time stamp of the file is not read, but I am not that much of an expert to know what is going wrong. It seems to always come down to the print line. Any insight is appreciated. Cheers.

Upvotes: 0

Views: 348

Answers (3)

Hans Fong
Hans Fong

Reputation: 1

Thank you guys. After two days I got it figured out.

You were both right about the path not being specified enough. Fixed that.

Miller: the glob thing worked after I added use File::stat. I never worked with globs, so thanks for steering me in that direction. Learned a lot from it. Cheers.

In the end I tried the OOP interface for stat after fiddling for an hour with single file examples:

my $file_time = stat("$directory/$file_name")->mtime;

This got me what I wanted, so I tried the same method with the array element number:

my $file_time = (stat("$file_name"))->[9] or die "No $_: $!";

This also worked. So it all came down to adding "->"

This is my final code that works. I know it can be prettier/better/more efficient, but for now it is fine with me, because I wrote it myself. Time to get on with some additions because it is going to be a script only run on my own machine to handle some automation tasks.

#!/usr/bin/perl
use strict;
use warnings;
use File::stat;
use Time::localtime;

my $directory = '/home/hans/.config/cqrlog/database';
opendir (DIR, $directory) or die $!;
my @files = (readdir(DIR));
closedir(DIR);

foreach $_ (@files) {

# Use a regular expression to find files ending with .gz
    if ($_ =~ m/\.gz$/) {
#   my $file_time = stat("$directory/$_")->mtime;
my $file_time = (stat("$directory/$_"))->[9] or die "No $_: $!";
print "$_\n";
print "$file_time\n";
    }
}

Upvotes: 0

Miller
Miller

Reputation: 35198

stat returns the empty list if stat fails. Therefore consider test the error code, especially when facing a problem like you were:

my $st = stat($_) or die "No $_: $!";

This would've returned:

No <filename.gz>: No such file or directory at ...

As mpapec already pointed out, this is because you aren't including the path information in the stat call. There are three possible solutions:

1) chdir to the directory your iterating over

chdir $directory;

2) Use a glob instead of readdir

#!/usr/bin/perl

use strict;
use warnings;

my $directory = '/home/hans/.config/cqrlog/database';

for my $file_name (glob("$directory/*.gz")) {
    my $st = stat($file_name) or die "No $file_name: $!";
    my $file_time = $st->[9];
    print "$file_time\n";
}

3) Or manually add the path to the fqfn

my @file_time_array = stat("$directory/$_") or die "No $_: $!";

Upvotes: 0

mpapec
mpapec

Reputation: 50647

Instead of

my $file_time = (stat($_))[9];

try

my $file_time = (stat("$directory/$_"))[9];

otherwise you're looking for /home/hans/.config/cqrlog/database files in the current directory which could work ONLY if you're already in mentioned directory.

Upvotes: 1

Related Questions