【问题标题】:How to get true file creation date in R, on Unix systems?如何在 Unix 系统上获取 R 中的真实文件创建日期?
【发布时间】:2014-06-12 16:15:52
【问题描述】:

我正在尝试从 R 获取文件创建日期,并且我了解在某些不将其存储在任何地方的操作系统上,可能根本无法检索此信息。但是,我不确定当它(至少理论上)可检索时如何一般地检索它。

在 Windows 上,这很简单,因为来自file.infoctime 提供了此信息,供参考,这是来自?file.info 的相关摘录

三个文件时间的含义取决于操作系统和文件系统。在 Windows 本地文件系统上,ctime 是文件创建时间(在大多数类 Unix 文件系统上没有记录的时间)。

然而,尽管大多数 unix 系统不记录此信息(如帮助中所指出的),但某些基于 unix 的系统(例如 OS X)实际上会存储此信息。例如,在 OS X 上,系统命令 metadata ls mdls 将打印文件元数据并将kMDItemContentCreationDate(文件的实际创建日期)列为文件属性之一。

我的问题是,对于从文件元数据中获取文件创建日期(如果有的话),人们有什么建议? (例如,特别是在有系统命令但没有直接 R 调用的 OS X 的情况下)

更新

感谢来自 cmets 的信息 + 有关 SO 和 SE herehere 的详细信息,我想出了一种方法来在跟踪创建日期并具有 @ 的 OS X 类型 unix 平台上的 R 中解决此问题987654323@。但是,我仍然无法弄清楚如何在其他跟踪创建日期但没有此版本stat 的 Linux 系统上的 R 中执行此操作。在unix SE 的这个答案中,建议可以使用debugfs + stat 检索此信息,即使stat 本身没有报告它(提供文件系统记录生日),但该解决方案我无法开始工作(只有我可以测试的 linux 没有debugfs)。无论如何,这就是我得到了多远:

get_birthdate <- function(filepath) {
  switch(Sys.info()[['sysname']],
         Windows = {
           # Windows
           file.info(filepath)$ctime
         },
         Darwin = {
           # OS X
           cmd <- paste('stat -f "%DB"', filepath) # use BSD stat command
           ctime_sec <- as.integer(system(cmd, intern=T)) # retrieve birth date in seconds from start of epoch (%DB)
           as.POSIXct(ctime_sec, origin = "1970-01-01", tz = "") # convert to POSIXct
         },
         Linux  = {
           # Linux
           stop("not sure how to do this")
         })
}

【问题讨论】:

  • 在 unix 系统上,ctime(可能)是创建目录条目的时间,但可能与创建文件的时间不同。这是因为 unix 文件系统上的文件可能有多个指向它们的目录条目; Windows 不允许这样做,因此唯一的 ctime 将是实际的文件创建时间。
  • 好吧,我知道你不能只在 Unix 上使用 file.info('yourfilename')['ctime']
  • 是的,不幸的是,unix上的file.info中的ctime只是“最后一次状态更改”的时间,如果我理解正确的话,基本上将任何文件内容的最后一次更改时间记录为以及文件所有权等方面的非数据更改,也就是说,它更像mtime,并且不包含有关创建时间(目录条目或其他)的任何信息
  • file.info 使用stat,对于大多数 Linux 文件系统,您不会获得创建时间。 stat 返回最后一个 [访问|mod|状态更改]。 Ext4 (linux) 存储创建时间 (crtime) 但您无法从 R 获取它。NTFS 也存储真实创建时间,但我也不知道如何从 R 获取它。这个SE:unix.stackexchange.com/questions/50177/birth-is-empty-on-ext4 线程可能会有所帮助。

标签: r filesystems system-calls fileinfo


【解决方案1】:

按照其他人的指示,这应该工作得相当合理。 不幸的是,它需要 root 权限(由于debugfs)而且它还不是很高效(特别是在正则表达式上有点快'n 脏,但这里是早上 01:00 点:))。

顺便说一句,我们将寻呼机设置为cat(使debugfs在标准输出上打印),找到文件存储在哪个设备中以便正确使用debugfs,最后得到统计数据并详细说明有点。

一般来说,在 UNIX 中,一旦你有一个 bash 命令来读取它在 R 中的输出,你必须在读取模式(默认)和 readLines 中使用 pipe

在 Debian Gnu Linux 中完成测试。

np350v5c:/home/l# R
> my.file <- "/etc/network/interfaces"
> 
> setup_pager <- function() {system("export PAGER=cat")}
> 
> where_is <- function(file) {
      con <- pipe(sprintf("df %s", file))
      res <- strsplit(readLines(con)[2], " ")[[1]][1]
      close(con)
      res
  }
> 
> where_is(my.file) # could be /dev/sda1 as well, depending on /etc/fstab
[1] "/dev/disk/by-uuid/9ce40c2b-60d8-40b1-890f-1e5da4199c88"
> 
> my.command <- sprintf("debugfs -R 'stat %s' %s",
                        my.file,
                        where_is(my.file))
> 
> ## root privileges especially here ..                                           
> setup_pager()
> con <- pipe(my.command)
> debugfs <- readLines(con)
debugfs 1.42.9 (4-Feb-2014)
> close(con)
> 
> my.date <- gsub("^crtime:.+-- ", "", grep("^crtime", debugfs, value = TRUE))
> my.date
[1] "Tue Feb 19 00:07:21 2013"
> strptime(tolower(substr(my.date, 5, nchar(my.date))),
           format = "%b %d %H:%M:%S %Y")
[1] "2013-02-19 00:07:21 CET"

HTH,卢卡

【讨论】:

  • 非常好,非常感谢您解决这个问题!一个简短的评论,我认为即使在 unix 系统上,您也可以通过使用 system(., intern=T) 来避免 pipereadLines 组合,例如,您的 where_is 函数也可以像这样工作:where_is &lt;- function(file) strsplit(system(sprintf("df %s", file), intern = T)[2], " ")[[1]][1](至少在 Red Hat 服务器上我可以测试这个 - 不幸的是没有 root 访问权限来完全实现它)
  • @sebkopf 是(已测试),不知道实习生参数。谢谢
【解决方案2】:

我知道我在这里玩游戏有点晚了,但这里有一个适用于 unix/Mac OS 的非常简单的解决方案:

file.name <- "~/dir/file.extension"
df$file_created_dt <- system(paste0("stat -f %SB ", file.name), intern = T)

然后你可以随意格式化它:

df$file_created_dt <- as.POSIXct(df$file_created_dt, format = "%b %d %H:%M:%S %Y", origin = "1970-01-01 00:00:00", tz = "your/timezone")

【讨论】:

    猜你喜欢
    • 2018-06-07
    • 1970-01-01
    • 2011-05-19
    • 2016-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-16
    相关资源
    最近更新 更多