2010-03-18 13 views
8

Quiero reproducir la salida de ls --full-time de un script de Perl para evitar la sobrecarga de llamar al ls varios miles de veces. Esperaba usar la función stat y obtener toda la información de allí. Sin embargo, la marca de tiempo en la salida ls usa el reloj de alta resolución, por lo que también incluye la cantidad de nanosegundos (según los documentos de GNU, esto se debe a que --full-time equivale a --format=long --time-style=full-iso, y el estilo de tiempo iso completo incluye los nanosegundos).¿Cómo puedo obtener el mtime de alta resolución para un enlace simbólico en Perl?

Encontré el módulo Time::HiRes, que anula la función de estadísticas estándar con una que devuelve atime/mtime/ctime como números de punto flotante, pero no hay anulación para lstat. Esto es un problema, porque al llamar a stat en un enlace simbólico se devuelve información para el archivo vinculado, no para el enlace en sí.

Así que mi pregunta es: ¿dónde puedo encontrar una versión de lstat que devuelva atime/mtime/ctime de la misma manera que Time :: HiRes :: stat? En su defecto, ¿hay otra forma de obtener el tiempo de modulación para un enlace simbólico en alta resolución (que no sea llamar a ls)?

+2

¿Necesita una solución portátil o solo hay un sistema operativo objetivo? – mob

Respuesta

3

Su mejor opción sería solicitar que lstat se agregue a Time::HiRes. De hecho, probablemente puedas hacerlo tú mismo. Apostaría que todo lo que necesita hacer es copiar la función que se inicia

void 
stat(...) 

en HiRes.xs, cambie stat(...) a lstat(...) & OP_STAT a OP_LSTAT, añadir lstat a @EXPORT_OK en HiRes.pm, y recompilar. Luego envíe un parche para que otros puedan beneficiarse.

+0

Cambiar OP_STAT a OP_LSTAT no funcionaría ya que PL_ppaddr [OP_LSTAT] es lo mismo que PL_ppaddr [OP_STAT] ya que Perl_pp_lstat es implementado internamente por Perl_pp_stat ... Pero +1 por el hecho de que su respuesta me dio una idea de cómo abordar el problema . –

4

Si usted está dispuesto a utilizar Inline :: C, esto va a funcionar con Linux reciente

#!/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]); 
2

trabajan los siguientes cambios. Esto esencialmente contiene cambios tanto en el módulo HiRes.pm como en el archivo xs.

En 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; 
} 

También se ha añadido a la lista de lstat @EXPORT_OK.

En 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))); 
+0

¿Ha enviado un parche a [RT] (https://rt.cpan.org/Public/Dist/Display.html?Name=Time-HiRes)? –

+0

@BradGilbert - Todavía no. También encontré otra forma de completar este cambio por completo en el archivo xs. aún decidiendo cuál sería la mejor opción –

1

Para el registro, lstat ha sido añadido a Tiempo contrataciones versión 1.9726 en agosto de 2013.

Ver https://rt.cpan.org/Public/Bug/Display.html?id=83356 para más detalles.

Sin embargo, todavía está 1.9725 incluido en la última versión estable de perl a partir del 30/01/2014 (5.18.2). Sin embargo, se superó a 1.9726 en la versión de desarrollo en 5.19.3.

Tenga en cuenta que (a partir del perl 5.19.8), independientemente de si Time::HiRes 's lstat es utilizarse o no, de -M/-A/-C todavía no hacer granularidad sub-segundo (archivos con tiempo en el mismo segundo se muestran como que tienen la misma edad) Perl, por lo que todavía no puede hacer cosas como sort {-M $a <=> -M $b} @files para ordenar archivos por fecha de modificación.

Cuestiones relacionadas