我有一个名为foo的脚本。R包含另一个脚本other。R,在同一个目录下:

#!/usr/bin/env Rscript
message("Hello")
source("other.R")

但我想让R找到另一个。R,不管当前工作目录是什么。

换句话说,就是foo。R需要知道自己的路径。我该怎么做呢?


当前回答

在我看来,从R脚本的获取路径中得到的rakensi的答案是最正确和真正精彩的。然而,它仍然是一个包含哑函数的黑客。我在这里引用它,是为了让别人更容易发现。

sourceDir <- getSrcDirectory(函数(dummy) {dummy})

这给出了放置语句的文件的目录(在那里定义了dummy函数)。然后可以使用它来设置工作目录并使用相对路径。

setwd(sourceDir)
source("other.R")

或者创建绝对路径

 source(paste(sourceDir, "/other.R", sep=""))

其他回答

#!/usr/bin/env Rscript
print("Hello")

# sad workaround but works :(
programDir <- dirname(sys.frame(1)$ofile)
source(paste(programDir,"other.R",sep='/'))
source(paste(programDir,"other-than-other.R",sep='/'))

参见R.utils包的findSourceTraceback(),其中

查找source()在所有调用帧中生成的所有'srcfile'对象。 这使得可以找出当前由source()编写脚本的文件。

99%的情况你可以简单地使用:

sys.calls()[[1]] [[2]]

它将不适用于脚本不是第一个参数的疯狂调用,即source(some args, file="myscript")。在这些奇特的情况下使用@hadley's。

我自己刚算出来的。为了确保脚本的可移植性,总是以以下开头:

wd <- setwd(".")
setwd(wd)

It works because "." translates like the Unix command $PWD. Assigning this string to a character object allows you to then insert that character object into setwd() and Presto your code will always run with its current directory as the working directory, no matter whose machine it is on or where in the file structure it is located. (Extra bonus: The wd object can be used with file.path() (ie. file.path(wd, "output_directory") to allow for the creation of a standard output directory regardless of the file path leading to your named directory. This does require you to make the new directory before referencing it this way but that, too, can be aided with the wd object.

或者,下面的代码执行完全相同的事情:

wd <- getwd()
setwd(wd)

或者,如果你不需要对象中的文件路径,你可以简单地:

setwd(".")

通过查看调用堆栈,我们可以获得正在执行的每个脚本的文件路径,其中最有用的两个可能是当前正在执行的脚本,或者是要获取的第一个脚本(条目)。

script.dir.executing = (function() return( if(length(sys.parents())==1) getwd() else dirname( Filter(is.character,lapply(rev(sys.frames()),function(x) x$ofile))[[1]] ) ))()

script.dir.entry = (function() return( if(length(sys.parents())==1) getwd() else dirname(sys.frame(1)$ofile) ))()