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

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

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

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


当前回答

frame_files <- lapply(sys.frames(), function(x) x$ofile)
frame_files <- Filter(Negate(is.null), frame_files)
PATH <- dirname(frame_files[[length(frame_files)]])

不要问我它是如何工作的,因为我已经忘记了:/

其他回答

我也有这个问题,上面的解决方案都不适合我。也许是来源之类的,但还不够清楚。

我找到了这个,对我来说很优雅的解决方案:

paste0(gsub("\\", "/", fileSnapshot()$path, fixed=TRUE),"/")

其中重要的是fileSnapshot(),它提供了关于文件的大量信息。它返回一个包含8个元素的列表。当您选择path作为列表元素时,路径将以\\作为分隔符返回,因此其余代码只是更改这一点。

我希望这能有所帮助。

我喜欢steamer25的解决方案,因为它似乎是最健壮的。然而,当在RStudio中调试时(在windows中),路径不会被正确设置。原因是,如果在RStudio中设置了断点,那么源文件将使用另一个“调试源”命令,该命令将脚本路径设置得稍微不同。下面是我目前正在使用的最终版本,它解释了调试时RStudio中的这种替代行为:

# @return full path to this script
get_script_path <- function() {
    cmdArgs = commandArgs(trailingOnly = FALSE)
    needle = "--file="
    match = grep(needle, cmdArgs)
    if (length(match) > 0) {
        # Rscript
        return(normalizePath(sub(needle, "", cmdArgs[match])))
    } else {
        ls_vars = ls(sys.frames()[[1]])
        if ("fileName" %in% ls_vars) {
            # Source'd via RStudio
            return(normalizePath(sys.frames()[[1]]$fileName)) 
        } else {
            # Source'd via R console
            return(normalizePath(sys.frames()[[1]]$ofile))
        }
    }
}

我喜欢这种方法:

this.file <- sys.frame(tail(grep('source',sys.calls()),n=1))$ofile
this.dir <- dirname(this.file)

在我看来,从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='/'))