获取 R 脚本的路径

有没有一种方法可以通过编程的方式在脚本内部找到 R 脚本的路径?

我问这个问题是因为我有几个使用 RGtk2的脚本,并从.glade 文件加载 GUI。

在这些脚本中,我必须在开头放置一个 setwd("path/to/the/script")指令,否则。将找不到 glade 文件(位于同一目录中)。

这很好,但是如果我将脚本移动到另一个目录或另一台计算机,我必须更改路径。我知道,没什么大不了的,但是如果能有这样的东西就好了:

setwd(getScriptPath())

那么,是否存在类似的函数呢?

57742 次浏览

如果将代码封装在包中,则始终可以查询包目录的某些部分。
下面是来自 RGtk2包的一个示例:

> system.file("ui", "demo.ui", package="RGtk2")
[1] "C:/opt/R/library/RGtk2/ui/demo.ui"
>

您可以对源代码中的目录 inst/glade/执行同样的操作,该目录将成为安装包中的目录 glade/,而且 system.file()将在安装时为您计算路径,与操作系统无关。

使用 source("yourfile.R", chdir = T)

利用 Rscript 的隐式“—— file”参数

当使用“ Rscript”(脚本文件)调用脚本时,脚本的完整路径作为系统参数给出。下面的函数利用这一点解压缩脚本目录:

getScriptPath <- function(){
cmd.args <- commandArgs()
m <- regexpr("(?<=^--file=).+", cmd.args, perl=TRUE)
script.dir <- dirname(regmatches(cmd.args, m))
if(length(script.dir) == 0) stop("can't determine script dir: please call the script with Rscript")
if(length(script.dir) > 1) stop("can't determine script dir: more than one '--file' argument detected")
return(script.dir)
}

这个答案对我很有用:

script.dir <- dirname(sys.frame(1)$ofile)

注意: 脚本必须来源,以返回正确的路径

我在 https://support.rstudio.com/hc/communities/public/questions/200895567-can-user-obtain-the-path-of-current-Project-s-directory-找到的

但我仍然不明白什么是 sys.frame (1) $ofile。我在 R 文档中没有找到任何关于这个的东西。有人能解释一下吗?

这对我有用:

getSrcDirectory(function(x) {x})

这将在脚本中定义一个匿名函数(不执行任何操作) ,然后确定该函数的源目录,即脚本所在的目录。

只适用于 RStudio:

setwd(dirname(rstudioapi::getActiveDocumentContext()$path))

这在 快跑ning 或 来源ing 文件时起作用。

#' current script dir
#' @param
#' @return
#' @examples
#' works with source() or in RStudio Run selection
#' @export
z.csd <- function() {
# http://stackoverflow.com/questions/1815606/rscript-determine-path-of-the-executing-script
# must work with source()
if (!is.null(res <- .thisfile_source())) res
else if (!is.null(res <- .thisfile_rscript())) dirname(res)
# http://stackoverflow.com/a/35842176/2292993
# RStudio only, can work without source()
else dirname(rstudioapi::getActiveDocumentContext()$path)
}
# Helper functions
.thisfile_source <- function() {
for (i in -(1:sys.nframe())) {
if (identical(sys.function(i), base::source))
return (normalizePath(sys.frame(i)$ofile))
}


NULL
}
.thisfile_rscript <- function() {
cmdArgs <- commandArgs(trailingOnly = FALSE)
cmdArgsTrailing <- commandArgs(trailingOnly = TRUE)
cmdArgs <- cmdArgs[seq.int(from=1, length.out=length(cmdArgs) - length(cmdArgsTrailing))]
res <- gsub("^(?:--file=(.*)|.*)$", "\\1", cmdArgs)


# If multiple --file arguments are given, R uses the last one
res <- tail(res[res != ""], 1)
if (length(res) > 0)
return (res)


NULL
}

如何使用系统和 shell 命令?对于 windows 1,我认为当您在 RStudio 中打开脚本时,它会将当前 shell 目录设置为脚本的目录。您可能需要添加 cd C: e.g 或任何您想要搜索的驱动器(例如 shell (‘ dir C: * file _ name/s’,值 = TRUE)-来转义转义字符)。只能用于唯一命名的文件,除非进一步指定子目录(对于 Linux,我从/开始搜索)。在任何情况下,如果您知道如何在 shell 中查找内容,那么这将提供一个在 R 中查找内容并返回目录的布局。应该工作,无论你是来源或运行的脚本,但我还没有充分探讨潜在的错误。

#Get operating system
OS<-Sys.info()
win<-length(grep("Windows",OS))
lin<-length(grep("Linux",OS))


#Find path of data directory
#Linux Bash Commands
if(lin==1){
file_path<-system("find / -name 'file_name'", intern = TRUE)
data_directory<-gsub('/file_name',"",file_path)
}
#Windows Command Prompt Commands
if(win==1){
file_path<-shell('dir file_name /s', intern = TRUE)
file_path<-file_path[4]
file_path<-gsub(" Directory of ","",file_path)
filepath<-gsub("\\\\","/",file_path)
data_directory<-file_path
}


#Change working directory to location of data and sources
setwd(data_directory)

谢谢你的功能,虽然我不得不调整它一点为我(W10) :

#Windows Command Prompt Commands
if(win==1){
file_path<-shell('dir file_name', intern = TRUE)
file_path<-file_path[4]
file_path<-gsub(" Verzeichnis von ","",file_path)
file_path<-chartr("\\","/",file_path)
data_directory<-file_path
}

许多这样的解决方案已经有好几年的历史了。虽然其中一些可能仍然有效,但是有充分的理由反对使用它们中的每一个(参见下面的链接源代码)。我有最好的解决方案(也是源代码) : 使用 here库。

原始示例代码:

library(ggplot2)
setwd("/Users/jenny/cuddly_broccoli/verbose_funicular/foofy/data")
df <- read.delim("raw_foofy_data.csv")

修改过的代码

library(ggplot2)
library(here)


df <- read.delim(here("data", "raw_foofy_data.csv"))

这个解决方案是最动态和健壮的,因为无论您是使用命令行、 RStudio、从 R 脚本调用等,它都可以正常工作。它使用起来非常简单,也非常简洁。

资料来源: https://www.tidyverse.org/articles/2017/12/workflow-vs-script/

在我的例子中,我需要一种方法来复制正在执行的文件,以备份原始脚本及其输出。这在研究中是相对重要的。在命令行上运行我的脚本时,对我有效的是这里提供的其他解决方案的混合,看起来像这样:

library(scriptName)
file_dir <- gsub("\\", "/", fileSnapshot()$path, fixed=TRUE)
file.copy(from = file.path(file_dir, scriptName::current_filename()) ,
to = file.path(new_dir, scriptName::current_filename()))

或者,可以在文件名中添加日期和 our 以帮助区分该文件和源文件,如下所示:

file.copy(from = file.path(current_dir, current_filename()) ,
to = file.path(new_dir, subDir, paste0(current_filename(),"_", Sys.time(), ".R")))

我找到了适合我的东西。 setwd(dirname(rstudioapi::getActiveDocumentContext()$path))

到目前为止,没有一种解决方案在任何情况下都有效。更糟糕的是,许多解决方案使用的是 setwd,因此使用的是 休息代码,这些代码期望工作目录是 工作目录ーー也就是代码的 使用者所选择的代码(我意识到这个问题询问的是 setwd(),但这并不能改变这通常是一个坏主意的事实)。

R 没有内置的方法来确定当前正在运行的代码段的路径。

一个干净的解决方案需要一种管理非包代码的系统方法。“盒子”就是干这个的。使用“ box”,可以很容易地找到与当前正在执行的代码相关的目录:

box::file()

然而,这并不是 box 的目的; 这只是它实际工作的一个副作用: 它为 R 实现了一个合适的、现代的模块系统。这包括在(嵌套的)模块中组织代码,因此能够从模块中加载相对于当前运行的代码的代码。

为了用‘ box’加载代码,你不会使用例如 source(file.path(box::file(), 'foo.r')),而是使用

box::use(./foo)

然而,box::file()对于定位 资料(即 OP 的用例)仍然很有用。因此,例如,要从当前模块的路径定位文件 mygui.glade,您需要编写。

glade_path = box::file('mygui.glade')

而且(只要您使用的是‘ box’模块)这总是可行的,不需要任何修改,也不使用 setwd