我有一个名为foo.R
的脚本,它包括另一个脚本other.R
,两个脚本位于同一个目录中:
#!/usr/bin/env Rscript
message("Hello")
source("other.R")
但是我希望R
能够找到那个other.R
,无论当前的工作目录是什么。
换句话说,foo.R
需要知道它自己的路径。我该如何做到这一点?
我有一个名为foo.R
的脚本,它包括另一个脚本other.R
,两个脚本位于同一个目录中:
#!/usr/bin/env Rscript
message("Hello")
source("other.R")
但是我希望R
能够找到那个other.R
,无论当前的工作目录是什么。
换句话说,foo.R
需要知道它自己的路径。我该如何做到这一点?
scriptName
库
该库提供了current_filename()
函数,当通过RStudio进行源代码调用或通过R或RScript可执行文件调用时,会返回脚本的完整路径。
Package ‘scriptName’已从CRAN存储库中删除。
- 现在怎么办? :o - Bojan P.我喜欢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))
}
}
}
paste0(gsub("\\", "/", fileSnapshot()$path, fixed=TRUE),"/")
fileSnapshot()
能提供很多关于文件的信息。它返回一个包含 8 个元素的列表。当您选择 path
作为列表元素时,路径将以 \\
作为分隔符返回,因此代码的其余部分只需更改此处即可。我自己解决了这个问题。为了确保您的脚本可移植性,请始终以以下方式开始:
wd <- setwd(".")
setwd(wd)
或者,以下代码执行完全相同的操作:
wd <- getwd()
setwd(wd)
或者,如果你不需要在对象中使用文件路径,你可以简单地:
setwd(".")
setwd(".")
和(在您的情况下)setwd(wd)
都是毫无意义的操作。它们没有任何效果。 - Konrad RudolphSteamer25的方法有效,但仅当路径中没有空格时才有效。至少在macOS上,cmdArgs [match]
返回类似于 /base/some~+~dir~+~with~+~whitespace/
的内容,而针对 /base/some\ dir\ with\ whitespace/
。
我通过将"~+~"替换为普通空格来解决了这个问题。
thisFile <- function() {
cmdArgs <- commandArgs(trailingOnly = FALSE)
needle <- "--file="
match <- grep(needle, cmdArgs)
if (length(match) > 0) {
# Rscript
path <- cmdArgs[match]
path <- gsub("\\~\\+\\~", " ", path)
return(normalizePath(sub(needle, "", path)))
} else {
# 'source'd via R console
return(normalizePath(sys.frames()[[1]]$ofile))
}
}
foo.R
,而是知道其路径位置,如果您可以更改代码以始终从公共root
引用所有source
的路径,则以下内容可能会有所帮助:
假设:
/app/deeply/nested/foo.R
/app/other.R
那么这将起作用。
#!/usr/bin/env Rscript
library(here)
source(here("other.R"))
请参考https://rprojroot.r-lib.org/,了解如何定义项目根目录。
您可以将R脚本包装在bash脚本中,并像这样检索脚本的路径作为bash变量:
#!/bin/bash
# [environment variables can be set here]
path_to_script=$(dirname $0)
R --slave<<EOF
source("$path_to_script/other.R")
EOF
this.file <- sys.frame(tail(grep('source',sys.calls()),n=1))$ofile
this.dir <- dirname(this.file)
R -e "library(getopt); testscript.R"
调用该脚本,它仍然返回 NA。 - bokov