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?
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);
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 Use the builtin stat function. Or more specifically:
my $modtime = (stat($fh))[9]
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.
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.
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.
-M
, add the quotes "-M", since -X
removes results having X
... By the way, '-M' is what the OP wants. –
Tichon You could use stat() or the File::Stat module.
perldoc -f stat
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];
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";
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.
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.
© 2022 - 2024 — McMap. All rights reserved.
localtime
supposed to correct for timezone changes? Ie: file created in PST, then readmtime
from CET. I am getting confusing results. – Gowan