9

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

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

所以我的问题是——我在哪里可以找到与 Time::HiRes::stat 一样返回 atime/mtime/ctime 的 lstat 版本?如果做不到这一点,是否有另一种方法可以获取高分辨率符号链接的 modtime(调用 ls 除外)。

4

4 回答 4

3

如果您愿意使用 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]);
于 2010-03-18T23:21:12.770 回答
2

作为记录,lstat已于 2013 年 8 月添加到 Time-HiRes 版本 1.9726。

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

但是,它仍然1.9725包含在perl2014-01-31 (5.18.2) 的最新稳定版本中。不过在 5.19.3 的开发版本中它被撞到了 1.9726。

注意(从perl5.19.8 开始),无论是否使用'Time::HiRes s ,perl 的//仍然不做亚秒级粒度(时间在同一秒内的文件将显示为具有相同年龄),所以你仍然不能做一些事情,比如按修改时间对文件进行排序。lstat-M-A-Csort {-M $a <=> -M $b} @files

于 2014-01-31T12:31:00.373 回答
2

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

void
stat(...)

in HiRes.xs,更改stat(...)lstat(...)& OP_STATOP_LSTAT添加lstat@EXPORT_OKin HiRes.pm,然后重新编译。然后提交补丁,以便其他人受益。

于 2010-03-18T21:22:21.680 回答
1

以下更改有效。这实质上包含对 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)));
于 2012-01-11T11:49:55.283 回答