我有一个名为foo的脚本。R包含另一个脚本other。R,在同一个目录下:
#!/usr/bin/env Rscript
message("Hello")
source("other.R")
但我想让R找到另一个。R,不管当前工作目录是什么。
换句话说,就是foo。R需要知道自己的路径。我该怎么做呢?
我有一个名为foo的脚本。R包含另一个脚本other。R,在同一个目录下:
#!/usr/bin/env Rscript
message("Hello")
source("other.R")
但我想让R找到另一个。R,不管当前工作目录是什么。
换句话说,就是foo。R需要知道自己的路径。我该怎么做呢?
当前回答
我已经将这个问题的答案打包并扩展为rprojroot中的新函数thisfile()。也适用于编织与针织。
其他回答
我在一个高性能计算集群环境中工作。我在不同的地方开发代码,而不是在生产运行的地方。在开发过程中,我通常从命令行交互式地调用R(而不是使用RStudio)。有很多来源(“foo.R”)正在进行。
在生产运行期间,我通常编写一个bash脚本,尝试不同的参数,并在单独的目录中运行每一组参数。bash脚本利用了工作负载管理器(即SLURM)。在这种环境中,设置环境变量很简单。考虑到这一点,下面的解决方案最适合我。
其他。R
my_message <- function(){
return("R is awkward")
}
foo。R
srcpath = Sys.getenv("R_SRC")
# Check if runnning w/o setting R_SRC - presumably done in directory of development, i.e. /path/to/R/code
if(srcpath == ""){
srcpath="./"
}
source(sprintf("%s/other.R", srcpath))
string = my_message()
print(string)
如果从R交互式shell中运行,并且在/path/到/R/code中运行,那么简单
> source("foo.R")
如果不是从交互式shell运行,也不是从/path/to/R/code运行,首先设置环境变量R_SRC,然后调用Rscript
$ export R_SRC=/path/to/R/code/
$ Rscript /path/to/R/code/foo.R
我对上面的实现有问题,因为我的脚本是从符号链接目录操作的,或者至少这就是为什么我认为上面的解决方案不适合我。按照@ennuikiller的回答,我将Rscript包装在bash中。我使用pwd -P设置路径变量,它解析符号链接目录结构。然后将路径传递给Rscript。
Bash.sh
#!/bin/bash
# set path variable
path=`pwd -P`
#Run Rscript with path argument
Rscript foo.R $path
foo。R
args <- commandArgs(trailingOnly=TRUE)
setwd(args[1])
source(other.R)
在我看来,从R脚本的获取路径中得到的rakensi的答案是最正确和真正精彩的。然而,它仍然是一个包含哑函数的黑客。我在这里引用它,是为了让别人更容易发现。
sourceDir <- getSrcDirectory(函数(dummy) {dummy})
这给出了放置语句的文件的目录(在那里定义了dummy函数)。然后可以使用它来设置工作目录并使用相对路径。
setwd(sourceDir)
source("other.R")
或者创建绝对路径
source(paste(sourceDir, "/other.R", sep=""))
只是在上面的答案的基础上,作为安全检查,您可以添加一个包装器,当sys.frame(1)失败时(如果interactive() == TRUE可能会失败),或者源脚本不在主脚本所期望的位置时,它会要求用户找到文件。
fun_path = tryCatch(expr =
{file.path(dirname(sys.frame(1)$ofile), "foo.R")},
error = function(e){'foo.R'}
)
if(!file.exists(fun_path))
{
msg = 'Please select "foo.R"'
# ask user to find data
if(Sys.info()[['sysname']] == 'Windows'){#choose.files is only available on Windows
message('\n\n',msg,'\n\n')
Sys.sleep(0.5)#goes too fast for the user to see the message on some computers
fun_path = choose.files(
default = file.path(gsub('\\\\', '/', Sys.getenv('USERPROFILE')),#user
'Documents'),
caption = msg
)
}else{
message('\n\n',msg,'\n\n')
Sys.sleep(0.5)#goes too fast for the user to see the message on some computers
fun_path = file.choose(new=F)
}
}
#source the function
source(file = fun_path,
encoding = 'UTF-8')
请注意,getopt包提供了get_Rscript_filename函数,该函数使用与本文相同的解决方案,但已经在标准R模块中为您编写了该解决方案,因此您不必将“获取脚本路径”函数复制并粘贴到您编写的每个脚本中。