How do I get a file's last modified time in Perl?
Asked Answered
A

10

72

Suppose I have a filehandle $fh. I can check its existence with -e $fh or its file size with -s $fh or a slew of additional information about the file. How can I get its last modified time stamp?

Almetaalmighty answered 4/2, 2009 at 0:16 Comment(0)
A
111

Calling the built-in function stat($fh) returns an array with the following information about the file handle passed in (from the perlfunc man page for stat):

  0 dev      device number of filesystem
  1 ino      inode number
  2 mode     file mode  (type and permissions)
  3 nlink    number of (hard) links to the file
  4 uid      numeric user ID of file's owner
  5 gid      numeric group ID of file's owner
  6 rdev     the device identifier (special files only)
  7 size     total size of file, in bytes
  8 atime    last access time since the epoch
  9 mtime    last modify time since the epoch
 10 ctime    inode change time (NOT creation time!) since the epoch
 11 blksize  preferred block size for file system I/O
 12 blocks   actual number of blocks allocated

Element number 9 in this array will give you the last modified time since the epoch (00:00 January 1, 1970 GMT). From that you can determine the local time:

my $epoch_timestamp = (stat($fh))[9];
my $timestamp       = localtime($epoch_timestamp);

Alternatively, you can use the built-in module File::stat (included as of Perl 5.004) for a more object-oriented interface.

And to avoid the magic number 9 needed in the previous example, additionally use Time::localtime, another built-in module (also included as of Perl 5.004). Together these lead to some (arguably) more legible code:

use File::stat;
use Time::localtime;
my $timestamp = ctime(stat($fh)->mtime);
Almetaalmighty answered 4/2, 2009 at 0:50 Comment(2)
Is localtime supposed to correct for timezone changes? Ie: file created in PST, then read mtime from CET. I am getting confusing results.Gowan
Mentioning the use of File::stat is misleading, as this will provide an object oriented way of accessing the stat information, and accessing array elements directly won't work. There is no need to use File::stat to access e.g. (stat($fh))[9]Buckinghamshire
C
26

Use the builtin stat function. Or more specifically:

my $modtime = (stat($fh))[9]
Comedo answered 4/2, 2009 at 0:24 Comment(0)
B
19
my @array = stat($filehandle);

The modification time is stored in Unix format in $array[9].

Or explicitly:

my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
    $atime, $mtime, $ctime, $blksize, $blocks) = stat($filepath);

  0 dev      Device number of filesystem
  1 ino      inode number
  2 mode     File mode  (type and permissions)
  3 nlink    Number of (hard) links to the file
  4 uid      Numeric user ID of file's owner
  5 gid      Numeric group ID of file's owner
  6 rdev     The device identifier (special files only)
  7 size     Total size of file, in bytes
  8 atime    Last access time in seconds since the epoch
  9 mtime    Last modify time in seconds since the epoch
 10 ctime    inode change time in seconds since the epoch
 11 blksize  Preferred block size for file system I/O
 12 blocks   Actual number of blocks allocated

The epoch was at 00:00 January 1, 1970 GMT.

More information is in stat.

Borrero answered 4/2, 2009 at 0:25 Comment(0)
S
16

You need the stat call, and the file name:

my $last_mod_time = (stat ($file))[9];

Perl also has a different version:

my $last_mod_time = -M $file;

but that value is relative to when the program started. This is useful for things like sorting, but you probably want the first version.

Scalpel answered 4/2, 2009 at 0:25 Comment(0)
C
10

If you're just comparing two files to see which is newer then -C should work:

if (-C "file1.txt" > -C "file2.txt") {
{
    /* Update */
}

There's also -M, but I don't think it's what you want. Luckily, it's almost impossible to search for documentation on these file operators via Google.

Cheshvan answered 12/2, 2009 at 19:5 Comment(3)
To google -M, add the quotes "-M", since -X removes results having X... By the way, '-M' is what the OP wants.Tichon
It would be more natural to use "<" (to test if "file1.txt" is the newer one - as "-C" returns the age of the file, not the (creation) date).Bybee
Explanation of the difference between -M (content modification) and -C (inode change): unix.stackexchange.com/questions/132660/…Melquist
B
3

You could use stat() or the File::Stat module.

perldoc -f stat
Brnaby answered 4/2, 2009 at 0:25 Comment(0)
P
3

I think you're looking for the stat function (perldoc -f stat)

In particular, the item found at index 9 of the returned list (i.e., the 10th field) is the last modify time of the file, in seconds since the epoch.

So:

my $last_modified = (stat($fh))[9];

Primm answered 4/2, 2009 at 0:26 Comment(0)
K
2

On my FreeBSD system, stat just returns a bless.

$VAR1 = bless( [
                 102,
                 8,
                 33188,
                 1,
                 0,
                 0,
                 661,
                 276,
                 1372816636,
                 1372755222,
                 1372755233,
                 32768,
                 8
               ], 'File::stat' );

You need to extract mtime like this:

my @ABC = (stat($my_file));

print "-----------$ABC['File::stat'][9] ------------------------\n";

or

print "-----------$ABC[0][9] ------------------------\n";
Kassia answered 3/7, 2013 at 2:4 Comment(0)
F
1

This is very old thread, but I tried using the solution and could not get the information out of File::stat. (Perl 5.10.1)

I had to do the following:

my $f_stats = stat($fh);
my $timestamp_mod = localtime($f_stats->mtime);
print "MOD_TIME = $timestamp_mod \n";

Just thought I share in case anyone else had the same trouble.

Faythe answered 10/3, 2018 at 18:35 Comment(0)
L
1

Another alternative is: $^T - (-M $fh)*3600*24

Given that the OP asked about the -X builtin functions I thought this might be along the lines of what he was looking for. I prefer it to stat() in some circumstances myself, tho I'm not sure I could defend that stylistic decision...

This uses the fact that Perl maintains the script start time in $^T (perldoc perlvar for more details), and that -M returns the delta of that vs the mod time of the file, as a floating point fraction of a day. It is cryptic but very perlish and fits nicely in situations where you don't have a file handle already (-X can operate on a file path or filehandle).

p.s. I used to have trouble finding details on the -X builtins, until realized you can find the details with perldoc -f -X in most perl-enabled command-line environments.

Lownecked answered 24/4, 2023 at 19:10 Comment(3)
Remember that Stack Overflow isn't just intended to solve the immediate problem, but also to help future readers find solutions to similar problems, which requires understanding the underlying code. This is especially important for members of our community who are beginners, and not familiar with the syntax. Given that, can you edit your answer to include an explanation of what you're doing and why you believe it is the best approach?Angloamerican
Thanks for the nudge! I was thinking of expounding on it when I posted, but figured it was an old question and nobody would care =)Lownecked
Never know who it may help in the future. Most of stack overflows traffic come from people with the same issue. It is always important to ensure that answers provide enough detail that anyone, new to the language or not, can understand the solution.Angloamerican

© 2022 - 2024 — McMap. All rights reserved.