如何在Perl中获得符号链接的高分辨率mtime?

时间:2010-03-18 14:16:30

标签: perl symlink stat high-resolution

我想从Perl脚本重现ls --full-time的输出,以避免几千次调用ls的开销。我希望使用stat函数并从那里获取所有信息。但是,ls输出中的时间戳使用高分辨率时钟,因此它也包含纳秒数(根据GNU文档,这是因为--full-time相当于--format=long --time-style=full-iso,并且完整 - 时间风格包括纳秒。

我遇到了Time::HiRes模块,该模块覆盖了标准的stat函数,并将atime / mtime / ctime作为浮点数返回,但lstat没有覆盖。这是一个问题,因为在符号链接上调用stat会返回链接文件的信息,而不是链接本身的信息。

所以我的问题是 - 在哪里可以找到一个版本的lstat以与Time :: HiRes :: stat相同的方式返回atime / mtime / ctime?如果失败了,是否有另一种方法可以以高分辨率获取符号链接的modtime(除了调用ls)。

4 个答案:

答案 0 :(得分:4)

如果您愿意使用Inline :: C,这将适用于最近的Linux

#!/usr/bin/perl

use strict;
use warnings;

use Inline C => <<'EOC';

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

long mtime_nsec(char* fname)
{
    struct stat st;
    if (-1 == lstat(fname, &st))
        return -1;
    return (long)st.st_mtim.tv_nsec;
}
EOC

print mtime_nsec($ARGV[0]);

答案 1 :(得分:3)

您最好的选择是要求lstat添加到Time::HiRes。事实上,你可以自己做。我敢打赌,你需要做的就是复制启动的功能

void
stat(...)
HiRes.xs

,将stat(...)更改为lstat(...)&amp; OP_STATOP_LSTAT,在lstat中将@EXPORT_OK添加到HiRes.pm,然后重新编译。然后提交补丁,以便其他人可以受益。

答案 2 :(得分:2)

以下更改有效。这基本上包含对HiRes.pm模块和xs文件的更改。

在HiRes.pm

sub lstat { 
     my @lstatvalues = CORE::lstat(shift);   
     my @nanosecvalues =  Time::HiRes::lstatimplementation( $lstatvalues[8], $lstatvalues[9], $lstatvalues[10]);   
     ( $lstatvalues[8], $lstatvalues[9], $lstatvalues[10] ) = ( $nanosecvalues[0], $nanosecvalues[1], $nanosecvalues[2]);   
     return @lstatvalues;
}

还将lstat添加到@EXPORT_OK列表。

在HiRes.xs

void 
lstatimplementation(...)
PPCODE:
  UV atime = SvUV( ST( 0 ) );
  UV mtime = SvUV( ST( 1 ) );
  UV ctime = SvUV( ST( 2 ) );
  UV atime_nsec;
  UV mtime_nsec;
  UV ctime_nsec;
  hrstatns(atime, mtime, ctime,
       &atime_nsec, &mtime_nsec, &ctime_nsec);
  if (atime_nsec)
    XPUSHs( sv_2mortal(newSVnv(atime + 1e-9 * (NV) atime_nsec)));
  if (mtime_nsec)
    XPUSHs( sv_2mortal(newSVnv(mtime + 1e-9 * (NV) mtime_nsec)));
  if (ctime_nsec)
    XPUSHs( sv_2mortal(newSVnv(ctime + 1e-9 * (NV) ctime_nsec)));

答案 3 :(得分:2)

为了记录,2013年8月,Time-HiRes版本1.9726中添加了lstat

有关详细信息,请参阅https://rt.cpan.org/Public/Bug/Display.html?id=83356

但是,截至2014-01-31(5.18.2),它仍然1.9725包含在perl的最新稳定版本中。尽管如此,它在5.19.3的开发版本中也达到了1.9726。

请注意(截至perl 5.19.8),无论Time::HiRes&#39; s lstat是否 ,perl&# 39; s -M / -A / -C仍然不做亚秒级粒度(同一时间内的文件显示为年龄相同),所以你仍然不能像sort {-M $a <=> -M $b} @files那样按修改时间对文件进行排序。