功能串联路径?


73

是否存在连接路径的现有功能?

我知道实现起来并不难,但是...除了要注意尾部/(或\),我还需要注意适当的OS路径格式检测(即,我们写C:\dir\file还是/dir/file)。

正如我所说,我相信我知道如何执行它;问题是:我应该这样做吗?该功能已存在于现有R包中吗?

Answers:


117

是, file.path()

R> file.path("usr", "local", "lib")
[1] "usr/local/lib"
R> 

system.path()对于包中的文件,也同样有用:

R> system.file("extdata", "date_time_zonespec.csv", package="RcppBDT")
[1] "/usr/local/lib/R/site-library/RcppBDT/extdata/date_time_zonespec.csv"
R> 

extdata/date_time_zonespec.csv无论哪个文件都将获取文件

  1. 软件包的安装位置,以及
  2. 操作系统

这非常方便。最后,还有

R> .Platform$file.sep
[1] "/"
R> 

如果您坚持手动进行。


3
好答案。但是,该函数不处理尾部的“ /”,因此file.path("/home/user/","project")导致invalid /home/user//project。还有其他功能,还是我应该自己做(虽然很简单)?
亚当·里奇科夫斯基

如果以空字符串开头,就会得到它:file.path("", "home", "user", "project")产生"/home/user/project"
Dirk Eddelbuettel

4
注意/home/user//project/home/user/project都在Unix上有效。您在什么操作系统上?
flodel 2012年

@flodel Er ... Linux。但是我不知道。谢谢!而且似乎在Windows(在cmd.exe上)也有效!
亚当·里奇科夫斯基

这可能是R的基本知识,但是如果您已经拥有yourlist = list(“”,“ a”,“ b”,“ c”)并想将其转换为路径,do.call(file.path, yourlist)
Colin D

4

如果有人要,这是我自己的功能path.cat。它的功能可以与Python的os.path.join额外糖相媲美,它可以解释..

使用此功能,您可以分层构造路径,但是与不同,您可以file.path通过放置绝对路径使用户能够覆盖层次结构。作为补充糖,他可以将“ ..”放在他喜欢的路径上,具有明显的含义。

例如

  • path.cat("/home/user1","project/data","../data2") 产量 /home/user1/project/data2

  • path.cat("/home/user1","project/data","/home/user2/data") 产量 /home/user2/data

该函数仅将斜杠用作路径分隔符,这很好,因为R在Windows机器上透明地将其转换为反斜杠。

library("iterators") # After writing this function I've learned, that iterators are very inefficient in R.
library("itertools")

#High-level function that inteligentely concatenates paths given in arguments
#The user interface is the same as for file.path, with the exception that it understands the path ".."
#and it can identify relative and absolute paths.
#Absolute paths starts comply with "^\/" or "^\d:\/" regexp.
#The concatenation starts from the last absolute path in arguments, or the first, if no absolute paths are given.
path.cat<-function(...)
{
  elems<-list(...)
  elems<-as.character(elems)
  elems<-elems[elems!='' && !is.null(elems)]
  relems<-rev(elems)
  starts<-grep('^[/\\]',relems)[1]
  if (!is.na(starts) && !is.null(starts))
  {
    relems<-relems[1:starts]
  }
  starts<-grep(':',relems,fixed=TRUE)
  if (length(starts)==0){
    starts=length(elems)-length(relems)+1
  }else{
    starts=length(elems)-starts[[1]]+1}
  elems<-elems[starts:length(elems)]
  path<-do.call(file.path,as.list(elems))
  elems<-strsplit(path,'[/\\]',FALSE)[[1]]
  it<-ihasNext(iter(elems))
  out<-rep(NA,length(elems))
  i<-1
  while(hasNext(it))
  {
    item<-nextElem(it)
    if(item=='..')
    {
      i<-i-1
    } else if (item=='' & i!=1) {
      #nothing
    } else   {
      out[i]<-item
      i<-i+1
    }
  }
  do.call(file.path,as.list(out[1:i-1]))
}

1
很酷的注释,但是有一个重要的区别:normalizePath()要求路径必须在R服务器上实际存在。可能并非总是如此。对我来说,这是一个重要的区别。OTOH手册说normalizePath(),在Windows上将短名称转换为长名称。
亚当·里奇科夫斯基
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.