我想从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)。
答案 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_STAT
到OP_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
那样按修改时间对文件进行排序。