Как я могу получить mtime в высоком разрешении для символической ссылки в Perl? - PullRequest
9 голосов
/ 18 марта 2010

Я хочу воспроизвести вывод ls --full-time из сценария Perl, чтобы избежать затрат на вызов ls несколько тысяч раз. Я надеялся использовать функцию stat и получить всю информацию оттуда. Однако временная метка в выводе ls использует часы высокого разрешения, поэтому она также включает количество наносекунд (в соответствии с документацией GNU это происходит потому, что --full-time эквивалентно --format=long --time-style=full-iso, а full-iso стиль времени включает наносекунды).

Я наткнулся на модуль Time :: HiRes , который переопределяет стандартную функцию stat на функцию, которая возвращает atime / mtime / ctime как числа с плавающей запятой, но для lstat * 1011 переопределения нет *. Это проблема, потому что вызов stat для символической ссылки возвращает информацию для связанного файла, а не для самой ссылки.

Итак, мой вопрос заключается в следующем: где я могу найти версию lstat, которая возвращает atime / mtime / ctime так же, как Time :: HiRes :: stat? Если это не так, есть ли другой способ получить modtime для символической ссылки в высоком разрешении (кроме вызова ls).

Ответы [ 4 ]

4 голосов
/ 19 марта 2010

Если вы хотите использовать 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]);
3 голосов
/ 19 марта 2010

Лучше всего попросить добавить lstat к Time :: HiRes . На самом деле, вы могли бы сделать это самостоятельно. Могу поспорить, что все, что вам нужно сделать, это скопировать функцию, которая запускается

void
stat(...)

in HiRes.xs, измените stat(...) на lstat(...) & OP_STAT на OP_LSTAT, добавьте lstat к @EXPORT_OK в HiRes.pm и перекомпилируйте Затем отправьте патч, чтобы другие могли воспользоваться.

2 голосов
/ 31 января 2014

Для записи, lstat был добавлен в Time-HiRes версии 1.9726 в августе 2013 года.

Подробнее см. https://rt.cpan.org/Public/Bug/Display.html?id=83356.

Однако, это все еще 1.9725, который включен в последнюю стабильную версию perl по состоянию на 2014-01-31 (5.18.2). Хотя в версии для разработки в 5.19.3 она была увеличена до 1.9726.

Обратите внимание, что (по состоянию на perl 5.19.8), независимо от того, используется ли Time::HiRes lstat или нет, perl's -M / -A / -C по-прежнему не выполняйте детализацию с точностью до секунды (файлы со временем в одной и той же секунде будут отображаться как имеющие одинаковый возраст), поэтому вы все равно не можете выполнять такие операции, как sort {-M $a <=> -M $b} @files, для сортировки файлов по времени модификации.

2 голосов
/ 11 января 2012

Следующие изменения работают. Это по существу содержит изменения как модуля 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)));
...