【问题标题】:How can I copy a file in Perl and maintain its timestamp?如何在 Perl 中复制文件并维护其时间戳?
【发布时间】:2010-12-12 01:16:57
【问题描述】:

我正在使用 File::Copy 模块在 Perl 中复制文件:

#! /usr/bin/perl -w

use File::Copy;

copy("somefile.log", "copiedfile.log");

我想保留时间戳(尤其是修改时间),但这似乎不是一个选项。

有没有一种直接的方法来实现这一点而无需对“cp -p”进行系统调用?

【问题讨论】:

  • 保存时间戳(使用 stat),复制并再次应用时间戳(使用 utime)不行吗? (与“触摸”命令相同)
  • James,您在 brian 的回答中发表评论:“如果庞大的 Perl 库没有“复制和保留属性”功能(适用于 Linux),我会感到惊讶”,您怎么看?意思是“在Linux上工作”?如果你在谈论 cp -p,Linux 的源代码完全按照我上面的建议,使用 stat 和 utime 来做“保留”。这里是: (*(x->xstat)) (src_path, &src_sb) ... utb.actime = src_sb.st_atime; utb.modtime = src_sb.st_mtime; utime (dst_path, &utb)
  • Murali,Perl 有一个干净的“复制和保留属性”命令 rmscopy(请参阅下面 ghostdog74 的答案),但它仅在 VMS 系统上可用。在 Windows 上,我相信 syscopy 会完成这项工作,因为我认为在 Windows 上复制文件的标准语义会保留时间戳。在 Linux 上情况并非如此,因此三行“copy、stat、utime”组合似乎是最干净的“纯 Perl”解决方案。这对我来说似乎不优雅,但似乎是唯一的选择,无需进行反引号系统调用。

标签: perl file copy timestamp


【解决方案1】:

您可以使用stat 获取时间戳并使用utime 设置它。如果你能侥幸逃脱,system 并不总是坏事。你永远不会做出比cp -p 更快的东西。您会认为 File::Copy 会这样做,但在 unix 上却不会。阿比盖尔提交了RT #96158,但没有采取任何行动就关闭了。他有一个关于其损坏的演示文稿,但我没有在网上看到它。

【讨论】:

  • stat 和 utime 是一个选项,但并不真正符合“直截了当”的标准。也许我期望太高了,尽管如果庞大的 Perl 库没有“复制和保留属性”功能(适用于 Linux),我会感到惊讶。
  • 也许你对直截了当的定义不同。至于对缺少一个好的模块感到惊讶,那是因为没有人愿意相信 File::Copy 是多么糟糕,所以没有人想出更好的模块。
  • 看起来这是最好的解决方案。在我的程序中,我选择了cp -p,这对于我不打算分发的相当一次性的脚本来说是可以接受和简单的,但我认为干净的解决方案是将副本、stat 和 utime 包装成一个整洁的库函数。
【解决方案2】:

检查File::Copy。查看syscopyrmscopy。它在那里谈论时间戳。

【讨论】:

  • rmscopy 看起来很有希望,但仅适用于 VMS 系统(不是我正在使用的 Linux)。文档的格式有点不清楚,但我在我的 5.10.0 安装中签入了 Copy.pm 文件,并且没有定义 rmscopy。
  • 解释 perl 文档:syscopy 保留操作系统属性。除了在 Unix 上,它没有。
【解决方案3】:
#!/usr/bin/env perl 
# emulate unix "cp -p"
# to submit as an answer to
# https://stackoverflow.com/questions/1657296/how-can-i-copy-a-file-in-perl-and-maintain-its-timestamp
use strict; use warnings;
use Time::Local; use POSIX qw(strftime);
use File::Copy "cp"; # keep permissions identical

my $source='aaa';
my $target='junk';
unlink $target if -e $target;
my $source_mtime=(stat $source)[9];
cp $source, $target; 
# now all 4 times of $target are equal to the time when this command was executed, at least in bash
showfiledate($source);
showfiledate($target);
utime($source_mtime,$source_mtime,$target); 
# now atime, mtime, and birthtime are identical to $source mtime, at least in bash
showfiledate($target);

sub showfiledate
{
    my $file=shift;
    my $mtime=(stat $file)[9];
    my $dateJ=strftime '%Y-%m-%d %a %H:%M:%S', localtime($mtime);
    print $dateJ, ' ', $file,"\n";
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-02
    • 2012-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多