On Windows 7 and Mac OS 10.12.2 (with R 3.3.2), it appears that file.mtime()
severely rounds or truncates timestamps. I verified that file.create("my_file.txt"); print(as.numeric(file.mtime("my_file.txt")), digits = 22)
prints out several digits past the decimal on Linux, but everything past the decimal disappears on Windows 7 for the same my_file.txt
. The behavior for Mac OS 10.12.2 is similar to that of Windows 7. Is there a platform-independent way to get precise file timestamps in R?
You can wait about 2 weeks, at which point R 3.3.3 will solve this problem (at least for Windows). From the NEWS file:
(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.)
I think the new file.info
is likely the best way to go. If R-3.3.3 does not bring what you need (or in the interim, if it will), you can try to side-step it by capitalizing on the fact that stat
is likely installed in the base OS (I have not tested on a Mac):
as.POSIXct(system2("stat", args = c("-c", "%y", "my_file.txt"), stdout = TRUE))
# [1] "2017-02-15 11:24:13 PST"
This can be formalized in a function that does a skosh more for you:
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"
Since you asked for file.mtime
, I'm assuming "modified" is the most interesting to you, but it's easy enough to include some other file timestamps:
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"
Note that the lack of fractional seconds is an artifact of printing (as you stated), this can be remedied:
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"
Update: after testing on a Mac, I confirmed a couple of things (thanks to @HongOoi for the prod): (1) stat
is indeed different, not supporting the same command-line options, so this script would need to be updated; and (2) this answer suggests that the filesystem is not even storing sub-second resolution on the file times. If your filesystem type is HFS+, I think there may be nothing to be done here. If the underlying filesystem is different, you may have better results.
It's true that Windows does not come with a stat
executable. However, Git for Windows (which some argue is a necessity in an analyst/dev toolkit) does, under /Program Files/Git/usr/bin/stat.exe
. (In fact, my hack above was written on Windows, tested second on Ubuntu.)
Bottom line, unfortunately, you may not get what you want/need on MacOS depending on your filesystem type. I could not get the installed stat
to give sub-second resolution (even with its different arguments), suggesting that the 4 year old answer I referenced has not changed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With