Как получить время последнего изменения файла в perl в формате, возвращаемом командой diff? - PullRequest
4 голосов
/ 16 мая 2019

Я хочу отображать время в том же формате, который отображается командой linux diff.

D:\>diff -dub old.cfg new.cfg
--- old.cfg       2019-05-15 15:03:14.289950700 +0530
+++ new.cfg       2019-05-14 16:07:21.119695300 +0530

Я хочу показать время последнего изменения файла как 2019-05-15 15:03:14.289950700 +0530.
Я использовал stat, но я не получаю эту наносекундную часть. Ало, нужен часовой пояс в заданном формате. Я тоже попробовал Time::HiRes, но не смог получить.

my $dt = strftime("%Y-%m-%d %H:%M:%S", localtime((stat($old_file))[9]));

Возвращает: 2019-05-15 15:03:14. Не могли бы вы помочь мне добавить другую информацию?

Ответы [ 2 ]

4 голосов
/ 16 мая 2019

Я должен сначала сказать, что это не будет точным. Несмотря на то, что ваше оборудование, вероятно, поддерживает разрешение наносекунд, к тому времени, когда оно возвращается к программному обеспечению, оно в сотни раз отключено. Хотя с отметкой времени файла, предположительно используется только по отношению к другим файлам, это может быть менее важно.

Сказав это, единственный способ заявить о наносекундах - это использовать системные инструменты, поэтому stat

my ($ts) = grep { /^\s*Access: [0-9]{4}/ } qx(stat $file);
$ts =~ s/^\s*Access:\s+(.*)/$1/;

или, используя map в качестве фильтра

my ($ts) = map { /^\s*Access: ([0-9]{4}.*)/ ? $1 : () } qx(stat $file);

Одна проблема здесь, конечно, заключается в том, что мы должны проанализировать вывод; так что смотрите ваши справочные страницы и тестируйте свой stat, и не надейтесь на большую мобильность. Следите за изменениями в системе, поскольку выходной формат программ может измениться. Но я не нахожу наносекунды в Perl.

Для справки, на моем CentOS 7 (под bash и tcsh)

perl -we'$f=shift; print grep { /^\s*Access: [0-9]{4}/ } qx(stat $f)' file

отпечатки для случайного файла

Access: 2019-05-15 13:21:57.723987422 -0700

Еще раз, "нано" секунды не совсем точны.


Другой вариант, возможно, для более надежного анализа выходных данных, - это использовать ls с его --full-time

my $ts = join ' ', (split ' ', qx(ls --full-time $file))[5..7];

Как всегда, при запуске внешних команд тщательно составьте переменные и соответствующим образом заключите в кавычки / escape Хороший инструмент для цитирования: String :: ShellQuote . Или лучше вообще избегать оболочки, если в ней нет особой необходимости, используя для этого один из множества хороших модулей.

1 голос
/ 16 мая 2019

Это сложная задача.Первая задача состоит в том, чтобы получить разрешение в секунду для вашего файла, которое зависит как от операционной системы, так и от файловой системы.Вторая часть - получить смещение местного часового пояса.Однако все это выполнимо в современной системе.Вы были на правильном пути с Time::HiRes, но strftime() только даст вам часть пути.Вот пример программы, которая принимает файлы в качестве аргументов и печатает hi-res mtime в соответствии с вашими требованиями.

#!/usr/bin/perl

use strict;
use warnings;

use Time::HiRes qw(stat);
use Time::Piece;
use Time::Seconds;

sub timestr {
    my $t = localtime($_[0]);
    my $tstr = $t->strftime('%Y-%m-%d %H:%M:%S');
    if ($_[0] =~ /(\.\d+$)/) { $tstr .= $1 }
    my $off = $t->tzoffset;
    return sprintf('%s %+02d%02d', $tstr, int($off->hours), $off->minutes % 60);
}

for (@ARGV) {
    my @stat = stat($_);
    print "$_\n  ".($! ? "Error: $!" : timestr($stat[9]))."\n";
}
exit(0);

Пример вывода:

$ ./stat.pl stat.pl
stat.pl
  2019-05-16 20:02:38.76708 +1000

Много тяжелой работы в настоящее времясделано Time::Piece, но происходит небольшая хакерская попытка извлечь часть времени и преобразовать часовой пояс в желаемый формат (и я не тестировал его всесторонне).Возможно, вы захотите использовать sprintf() в исходном входящем значении, чтобы привести определенное количество знаков после запятой.Мой код просто честно воспроизводит оригинальную дробную часть.

Имейте в виду, что не все метки времени будут иметь дробную часть, даже в файловой системе, которая поддерживает разрешение менее секунды.Файл, возможно, был скопирован из источника, который не имеет субсекундного разрешения, например.

...