Get the path of current script

2019-03-12 21:06发布

问题:

I would like to set the working directory to the path of current script programmatically but first I need to get the path of current script.

So I would like to be able to do:

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

Just like the RStudio menu does:

So far I tried:

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 returns NULL

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

Returns: Error in file(filename, "r", encoding = encoding) : cannot open the connection In addition: Warning message: In file(filename, "r", encoding = encoding) : cannot open file '/script.R': No such file or directory

dirname(parent.frame(2)$ofile)

Returns: Error in dirname(parent.frame(2)$ofile) : a character vector argument expected ...because parent.frame is null

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

Returns: Null because frame_files is a list of 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))
    }
}

Returns: Error in path.expand(path) : invalid 'path' argument

Also I saw all answers from here, here, here and here. No joy.

Working with RStudio 1.1.383

EDIT: It would be great if there was no need for an external library to achieve this.

回答1:

In RStudio, you can get the path to the file currently shown in the source pane using

rstudioapi::getSourceEditorContext()$path

If you only want the directory, use

dirname(rstudioapi::getSourceEditorContext()$path)

If you want the name of the file that's been run by source(filename), that's a little harder. You need to look for the variable srcfile somewhere back in the stack. How far back depends on how you write things, but it's around 4 steps back: for example,

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

should print the same thing on the last two lines.



回答2:

Update August 2018

TLDR: The here package helps you build a path from the project's root folder no matter where in the folder hiearchy the R scripts or Rmd documents are stored.

The here package remains available on CRAN. The development version has been moved to github.com/r-lib/here. The points mentioned in the sites quoted below remain valid.

Previous answer

Read the Ode to the here package:

Do you: Have setwd() in your scripts? PLEASE STOP DOING THAT. This makes your script very fragile, hard-wired to exactly one time and place. As soon as you rename or move directories, it breaks. Or maybe you get a new computer? Or maybe someone else needs to run your code?

[...]

Classic problem presentation: Awkwardness around building paths and/or setting working directory in projects with subdirectories. Especially if you use R Markdown and knitr, which trips up alot of people with its default behavior of “working directory = directory where this file lives”. [...]

Install the here package:

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

Documentation of the here() function:

Starting with the current working directory during package load time, here will walk the directory hierarchy upwards until it finds a directory that satisfies at least one of the following conditions:

  • contains a file matching [.]Rproj$ with contents matching ^Version: in the first line
  • [... other options ...]
  • contains a directory .git

Once established, the root directory doesn't change during the active R session. here() then appends the arguments to the root directory.

The development version of the here package is available on github.



回答3:

If you're running an Rscript through the command-line etc

Rscript /path/to/script.R

The function below will assign this_file to /path/to/script

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


标签: r rstudio