【问题标题】:Get the path of current script获取当前脚本的路径
【发布时间】:2018-04-13 03:12:35
【问题描述】:

我想以编程方式将工作目录设置为当前脚本的路径,但首先我需要获取当前脚本的路径。

所以我希望能够做到:

current_path = ...retrieve the path of current script ...
setwd(current_path) 

就像 RStudio 菜单一样:

到目前为止我尝试过:

initial.options <- commandArgs(trailingOnly = FALSE)
file.arg.name <- "--file="
script.name <- sub(file.arg.name, "", initial.options[grep(file.arg.name, initial.options)])
script.basename <- dirname(script.name)

script.name 返回 NULL

source("script.R", chdir = TRUE)

返回: 文件错误(文件名,“r”,编码 = 编码):无法打开 连接另外:警告消息:在文件中(文件名,“r”, encoding = encoding) : 无法打开文件'/script.R': 没有这样的文件或 目录

dirname(parent.frame(2)$ofile)

返回:dirname(parent.frame(2)$ofile) 中的错误:需要一个字符向量参数 ...因为 parent.frame 为空

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

返回:空,因为 frame_files 是 0 的列表

thisFile <- function() {
    cmdArgs <- commandArgs(trailingOnly = FALSE)
    needle <- "--file="
    match <- grep(needle, cmdArgs)
    if (length(match) > 0) {
        # Rscript
        return(normalizePath(sub(needle, "", cmdArgs[match])))
    } else {
        # 'source'd via R console
        return(normalizePath(sys.frames()[[1]]$ofile))
    }
}

返回:path.expand(path) 中的错误:'path' 参数无效

我还看到了来自herehereherehere 的所有答案。 不开心。

使用RStudio 1.1.383

编辑:如果不需要外部库来实现这一点,那就太好了。

【问题讨论】:

  • source("&lt;path to file&gt;/script.R", chdir = TRUE) 可能会像帮助文件中所说的 chdir 一样起作用:* 如果 TRUE 且文件是路径名,则 R 工作目录临时更改为包含用于评估的文件的目录。* 错误消息你会说 R 在当前工作目录中找不到名为 script.R 的文件。
  • 我的文件名是 lpp.R,我确实给了这个名字......我记得在其他版本的 RStudio 中我很容易用父框架做到了,现在什么都没有
  • 在 R studio 项目文件夹中,最好假设所有文件路径都相对于项目的根目录。见Stop the working directory insanity。我个人不使用它,但建议使用 here 包来查找给定文件的位置。
  • @Imo -- 仅当您获取文件时才有效,但如果您使用 Rscript 调用它则无效。
  • @PaulRougieux -- 仅当您正在运行(或采购)的文件位于项目目录中时才有效。如果您在其他位置运行(或获取)文件,它将无法正常工作。

标签: r rstudio


【解决方案1】:

在 RStudio 中,您可以使用以下方式获取当前显示在源窗格中的文件的路径

rstudioapi::getSourceEditorContext()$path

如果你只想要目录,使用

dirname(rstudioapi::getSourceEditorContext()$path)

如果你想要source(filename) 运行的文件的名称,那就有点难了。您需要在堆栈中的某处查找变量srcfile。回退多远取决于你如何写东西,但大约是回退 4 步:例如,

fi <- tempfile()
writeLines("f()", fi)
f <- function() print(sys.frame(-4)$srcfile)
source(fi)
fi

应该在最后两行打印相同的内容。

【讨论】:

  • 这很好用。好消息是它与here 包相比具有更少的依赖关系。事实是,我希望在没有图书馆的情况下做到这一点。我会等一两天看看是否有人要添加一些东西,然后我会接受。谢谢。
  • 我刚刚在办公室的另一台 PC 上进行了全新安装。最新的 R Studio (1.1.383),最新的 R 版本 (R version 3.4.2 (2017-09-28))。现在我得到这个错误:Error: 'getSourceEditorContext' is not an exported object from 'namespace:rstudioapi'
  • 您使用的是什么版本的rstudioapi? 0.7 在 CRAN 上是最新的,但它是相当新的。
  • 我需要使代码可移植,将所有数据放在一个特定的文件夹中,并使其在其他人的电脑中尽可能快地工作。特别是那些只知道如何按下播放按钮并在没有任何用户干预的情况下查看代码生成结果的人
  • 这不会像Rscript test.R那样在终端中运行
【解决方案2】:

2019 年 3 月更新

基于 Alexis Lucattini 和 user2554330 的答案,使其可在命令行和 RStudio 上运行。还解决了“as_tibble”弃用消息

library(tidyverse)
getCurrentFileLocation <-  function()
{
    this_file <- commandArgs() %>% 
    tibble::enframe(name = NULL) %>%
    tidyr::separate(col=value, into=c("key", "value"), sep="=", fill='right') %>%
    dplyr::filter(key == "--file") %>%
    dplyr::pull(value)
    if (length(this_file)==0)
    {
      this_file <- rstudioapi::getSourceEditorContext()$path
    }
    return(dirname(this_file))
}

【讨论】:

  • 这确实有效,应该是所有相关问题的公认答案。
  • 不错。在if (length ...) { } 内,在this_file &lt;- ... 下面我添加了if(this_file=="") message("You are running code in RStudio in a new R script window, so the filename is blank.")
【解决方案3】:

2018 年 8 月更新

TLDRhere 包可帮助您从项目的根文件夹构建路径,无论 R 脚本或 Rmd 文档存储在文件夹层次结构中的哪个位置。

here 包在 CRAN 上仍然可用。开发版已移至github.com/r-lib/here。以下引用的网站中提到的要点仍然有效。

上一个答案

阅读Ode to the here package

你: 你的脚本中有 setwd() 吗?请停止这样做。 这使您的脚本非常脆弱,硬连线到一个时间和地点。一旦重命名或移动目录,它就会中断。或者,也许你买了一台新电脑?或者也许其他人需要运行您的代码?

[...]

经典问题演示:在带有子目录的项目中构建路径和/或设置工作目录的尴尬。特别是如果你使用 R Markdown 和 knitr,它的默认行为是“工作目录 = 此文件所在的目录”,这会让很多人感到困惑。 [...]

安装here 包:

install.packages("here")
library(here)
here()
here("construct","a","path")

here() 函数的文档:

在包加载时从当前工作目录开始, 这里将向上遍历目录层次结构,直到找到 至少满足以下条件之一的目录:

  • 包含一个匹配 [.]Rproj$ 且内容匹配 ^Version: in 第一行
  • [...其他选项...]
  • 包含一个目录.git

一旦建立,根目录在活动期间不会改变 R 会话。 here() 然后将参数附加到根目录。

here package is available on github的开发版。

【讨论】:

  • 这仅适用于sourceing 或Rscripting 同一项目树中的文件。例如,如果您正在调用位于其他地方的实用程序脚本,这将不起作用。
  • 假设 R 不是为实际可靠的开发而设计的。如果您有多个相互依赖的包,那么相对于给定文件路径导入是非常困难的。您唯一的选择是从根脚本全局导入所有内容。这对于可靠的开发是不可接受的。
  • @PaulRougieux 这与加载数据无关。这是关于导入其他 R 文件。例如必须使用 source()。与 python 导入相比,它非常糟糕,因为您必须使用非常糟糕的技巧来确保正确可靠的导入。当您必须编写可用于生产的代码并因此具有一定程度的控制权时,这一点非常重要。
  • @PaulRougieux 这也不是包装问题。您不能有嵌套的层次结构或文件 A 在同一代码库中导入文件 B(例如,在属于同一包的不同文件中的代码段之间)。
  • 这不是 R 包的工作方式,你有一个包命名空间,函数在该命名空间内相互调用。
【解决方案4】:

如果您通过命令行等运行 Rscript

Rscript /path/to/script.R

下面的函数会将this_file分配给/path/to/script

library(tidyverse)
get_this_file <- function(){
    commandArgs() %>% 
       tibble::enframe(name=NULL) %>%
       tidyr::separate(col=value, into=c("key", "value"), sep="=", fill='right') %>%
       dplyr::filter(key == "--file") %>%
       dplyr::pull(value)
}
this_file <- get_this_file()

【讨论】:

    【解决方案5】:

    这是一个自定义函数,用于在 R、RStudio 或 Rscript 中获取文件的路径:

    stub <- function() {}
    thisPath <- function() {
      cmdArgs <- commandArgs(trailingOnly = FALSE)
      if (length(grep("^-f$", cmdArgs)) > 0) {
        # R console option
        normalizePath(dirname(cmdArgs[grep("^-f", cmdArgs) + 1]))[1]
      } else if (length(grep("^--file=", cmdArgs)) > 0) {
        # Rscript/R console option
        scriptPath <- normalizePath(dirname(sub("^--file=", "", cmdArgs[grep("^--file=", cmdArgs)])))[1]
      } else if (Sys.getenv("RSTUDIO") == "1") {
        # RStudio
        dirname(rstudioapi::getSourceEditorContext()$path)
      } else if (is.null(attr(stub, "srcref")) == FALSE) {
        # 'source'd via R console
        dirname(normalizePath(attr(attr(stub, "srcref"), "srcfile")$filename))
      } else {
        stop("Cannot find file path")
      }
    }
    

    https://gist.github.com/jasonsychau/ff6bc78a33bf3fd1c6bd4fa78bbf42e7

    【讨论】:

      【解决方案6】:

      获取当前脚本路径的另一个选项是funr::get_script_path(),您不需要使用 RStudio 运行脚本。

      【讨论】:

      • 什么是funr
      • 这是一个包,你可以找到更多关于它的信息here。在R中,即使在当前工作环境中没有附加包,也可以通过如下方式使用它们的功能package::function()
      • 假设您有一个位于/path/to/project/script.R 的脚本,并且在该脚本中您有一个语句funr::get_script_path(),它将返回一个值/path/to/project。注意:它返回的是当前文件的完整目录路径,而不是当前文件的完整路径,应该是/path/to/project/script.R。不过,该功能适用​​于我的情况。
      【解决方案7】:

      我遇到了所有这些问题,因为它们依赖于我无法使用的库(因为 packrat),直到设置工作目录(这就是我需要获取路径开始的原因)之后。

      因此,这是一种仅使用基本 R 的方法。(已编辑处理窗口中的 \ 字符以及路径中的 /)

      args = commandArgs()
      
      scriptName = args[substr(args,1,7) == '--file=']
      
      if (length(scriptName) == 0) {
        scriptName <- rstudioapi::getSourceEditorContext()$path
      } else {
        scriptName <- substr(scriptName, 8, nchar(scriptName))
      }
      
      pathName = substr(
        scriptName, 
        1, 
        nchar(scriptName) - nchar(strsplit(scriptName, '.*[/|\\]')[[1]][2])
      )
      
      

      【讨论】:

        【解决方案8】:

        如果您不想使用(或必须记住)代码,只需将鼠标悬停在脚本上,路径就会出现

        【讨论】:

          【解决方案9】:

          以下解决了三种情况的问题:RStudio 源按钮、RStudio R 控制台(source(...),如果文件仍在“源”窗格中)或通过Rscript 的操作系统控制台:

          this_file = gsub("--file=", "", commandArgs()[grepl("--file", commandArgs())])
          if (length(this_file) > 0){
            wd <- paste(head(strsplit(this_file, '[/|\\]')[[1]], -1), collapse = .Platform$file.sep)
          }else{
            wd <- dirname(rstudioapi::getSourceEditorContext()$path)
          }
          
          print(wd)
          

          【讨论】:

          • 针对 RStudio 进行了调整
          【解决方案10】:

          如果您从 Rstudio 或使用 Rscript 命令从命令行运行它,以下代码给出了正在运行的 Rscript 的目录:

          if (rstudioapi::isAvailable()) {
            if (require('rstudioapi') != TRUE) {
              install.packages('rstudioapi')
            }else{
              library(rstudioapi) # load it
            }
           wdir <- dirname(getActiveDocumentContext()$path)
          }else{
           wdir <- getwd()
          }
          
          setwd(wdir)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-01-21
            • 2011-03-09
            • 1970-01-01
            • 1970-01-01
            • 2011-01-28
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多