R file.mtime() 在 Mac OS 和 Windows 上的精度极差 7

R file.mtime() extremely poor precision on Mac OS and Windows 7

在 Windows 7 和 Mac OS 10.12.2(使用 R 3.3.2)上,似乎 file.mtime() 严重舍入或截断时间戳。我验证了 file.create("my_file.txt"); print(as.numeric(file.mtime("my_file.txt")), digits = 22) 在 Linux 上打印出小数点后的几位数字,但在 Windows 上小数点后的所有内容都消失了 7 对于相同的 my_file.txt。 Mac OS 10.12.2 的行为类似于 Windows 7. 是否有独立于平台的方法在 R 中获取精确的文件时间戳?

您可以等待大约 2 周,届时 R 3.3.3 将解决此问题(至少 Windows)。来自 NEWS 文件:

(Windows only.) file.info() now returns file timestamps including fractions of seconds; it has done so on other platforms since R 2.14.0. (NB: some filesystems do not record modification and access timestamps to sub-second resolution.)

我认为新的 file.info 可能是最好的选择。如果 R-3.3.3 没有带来你需要的东西(或者在过渡期间,如果它会的话),你可以尝试 side-step 它通过利用 stat 可能安装在基地中这一事实OS(我没有在 Mac 上测试过):

as.POSIXct(system2("stat", args = c("-c", "%y", "my_file.txt"), stdout = TRUE))
# [1] "2017-02-15 11:24:13 PST"

这可以在一个函数中形式化,为您做更多的事情:

my_mtime <- function(filenames, stat = c("modified", "birth", "access", "status"),
                     exe = Sys.which("stat")) {
  if (! nzchar(exe)) stop("'stat' not found")
  stat <- switch(match.arg(stat), birth = "%w", access = "%x", modified = "%y", status = "%z")
  filenames <- Sys.glob(filenames) # expand wildcards, remove missing files
  if (length(filenames)) {
    outs <- setNames(system2(exe, args = c("-c", stat, shQuote(filenames)), stdout = TRUE),
                     nm = filenames)
    as.POSIXct(outs)
  }
}

my_mtime("[bh]*")
#                  b-file.R                  h-file.R 
# "2017-02-14 05:46:34 PST" "2017-02-14 05:46:34 PST"

既然你要求 file.mtime,我假设 "modified" 是你最感兴趣的,但包含一些其他文件时间戳也很容易:

my_mtime("[bh]*", stat="birth")
#                  b-file.R                  h-file.R 
# "2017-02-13 22:04:01 PST" "2017-02-13 22:04:01 PST" 
my_mtime("[bh]*", stat="status")
#                  b-file.R                  h-file.R 
# "2017-02-14 05:46:34 PST" "2017-02-14 05:46:34 PST" 

请注意,缺少小数秒是打印造成的(如您所述),这可以补救:

x <- my_mtime("[bh]*", stat="status")
x
#                  b-file.R                  h-file.R 
# "2017-02-14 05:46:34 PST" "2017-02-14 05:46:34 PST" 
options(digits.secs = 6)
x
#                         b-file.R                         h-file.R 
# "2017-02-14 05:46:34.307046 PST" "2017-02-14 05:46:34.313038 PST" 
class(x)
# [1] "POSIXct" "POSIXt" 

更新:在 Mac 上测试后,我确认了几件事(感谢@HongOoi 的产品):(1) stat 确实不同,不支持相同的 command-line 选项,因此需要更新此脚本; (2) this answer 表明文件系统甚至没有存储文件时间的 sub-second 分辨率。如果你的文件系统类型是 HFS+,我想这里可能没什么可做的。如果底层文件系统不同,您可能会有更好的结果。

确实 Windows 没有附带 stat 可执行文件。然而,Git for Windows(有些人认为这是 analyst/dev 工具包中的必需品)在 /Program Files/Git/usr/bin/stat.exe 下确实如此。 (事实上​​,我上面的 hack 是在 Windows 上写的,在 Ubuntu 上测试过。)

最重要的是,不幸的是,根据您的文件系统类型,您可能无法在 MacOS 上获得 want/need 的内容。我无法让安装的 stat 给出 sub-second 分辨率(即使有不同的参数),这表明我引用的 4 年前的答案没有改变。