Learn R Programming

this.path (version 2.2.0)

sys.path: Determine Executing Script's Filename

Description

sys.path() returns the normalized path of the executing script.

sys.dir() returns the directory of sys.path().

Usage

sys.path(verbose = getOption("verbose"), original = FALSE,
         for.msg = FALSE, contents = FALSE, local = FALSE,
         default, else.)
sys.dir(verbose = getOption("verbose"), local = FALSE,
        default, else.)

Value

character string; the executing script's filename.

Arguments

verbose

TRUE or FALSE; should the method in which the path was determined be printed?

original

TRUE, FALSE, or NA; should the original or the normalized path be returned? NA means the normalized path will be returned if it has already been forced, and the original path otherwise.

for.msg

TRUE or FALSE; do you want the path for the purpose of printing a diagnostic message / / warning / / error? This will return NA_character_ in most cases where an error would have been thrown.

for.msg = TRUE will ignore original = FALSE, and will use original = NA instead.

contents

TRUE or FALSE; should the contents of the executing script be returned instead? In ‘Jupyter’, a list of character vectors will be returned, the contents separated into cells. Otherwise, if for.msg is TRUE and the executing script cannot be determined, NULL will be returned. Otherwise, a character vector will be returned. You could use as.character(unlist(sys.path(contents = TRUE))) if you require a character vector.

This is intended for logging purposes. This is useful in ‘RStudio’ and ‘VSCode’ when the source document has contents but no path.

local

TRUE or FALSE; should the search for the executing script be confined to the local environment in which set.sys.path() was called?

default

if there is no executing script, this value is returned.

else.

missing or a function to apply if there is an executing script. See tryCatch2() for inspiration.

Details

There are three ways in which R code is typically run:

  1. in ‘Rgui’ / / ‘RStudio’ / / ‘VSCode’ / / ‘Jupyter’ by running the current line / / selection with the Run button / / appropriate keyboard shortcut

  2. through a source call: a call to function source(), sys.source(), debugSource() in ‘RStudio’, compiler::loadcmp(), box::use(), knitr::knit(), plumber::plumb(), shiny::runApp(), targets, or testthat::source_file()

  3. from a shell, such as the Windows command-line / / Unix terminal

To retrieve the executing script's filename, first an attempt is made to find a source call. The calls are searched in reverse order so as to grab the most recent source call in the case of nested source calls. If a source call was found, the file argument is returned from the function's evaluation environment. If you have your own source()-like function that you would like to be recognized by sys.path(), please contact the package maintainer so that it can be implemented or use set.sys.path() / / wrap.source().

If no source call is found up the calling stack, then an attempt is made to figure out how R is running.

If R is being run from a shell, the shell arguments are searched for -f FILE or --file=FILE (the two methods of taking input from FILE). The last FILE is extracted and returned (ignoring -f - and --file=-). It is an error to use sys.path() if no arguments of either type are supplied.

If R is being run from a shell under Unix-alikes with -g Tk or --gui=Tk, sys.path() will throw an error. ‘Tk’ does not make use of its -f FILE, --file=FILE arguments.

If R is being run from ‘Rgui’, the source document's filename (the document most recently interacted with besides the R Console) is returned (at the time of evaluation). Please note that minimized documents WILL be included when looking for the most recently used document. It is important to not leave the current document (either by closing the document or interacting with another document) while any calls to sys.path() have yet to be evaluated in the run selection. It is an error for no documents to be open or for a document to not exist (not saved anywhere).

If R is being run from ‘RStudio’, the active document's filename (the document in which the cursor is active) is returned (at the time of evaluation). If the active document is the R console, the source document's filename (the document open in the current tab) is returned (at the time of evaluation). Please note that the source document will NEVER be a document open in another window (with the Show in new window button). Please also note that an active document open in another window can sometimes lose focus and become inactive, thus returning the incorrect path. It is best NOT to not run R code from a document open in another window. It is important to not leave the current tab (either by closing or switching tabs) while any calls to sys.path() have yet to be evaluated in the run selection. It is an error for no documents to be open or for a document to not exist (not saved anywhere).

If R is being run from ‘VSCode’, the source document's filename is returned (at the time of evaluation). It is important to not leave the current tab (either by closing or switching tabs) while any calls to sys.path() have yet to be evaluated in the run selection. It is an error for a document to not exist (not saved anywhere).

If R is being run from ‘Jupyter’, the source document's filename is guessed by looking for R notebooks in the initial working directory, then searching the contents of those files for an expression matching the top-level expression. Please be sure to save your notebook before using sys.path(), or explicitly use set.sys.path.jupyter().

If R is being run from ‘AQUA’, the executing script's path cannot be determined. Unlike ‘Rgui’, ‘RStudio’, and ‘VSCode’, there is currently no way to request the path of an open document. Until such a time that there is a method for requesting the path of an open document, consider using ‘RStudio’ or ‘VSCode’.

If R is being run in another manner, it is an error to use sys.path().

If your GUI of choice is not implemented with sys.path(), please contact the package maintainer so that it can be implemented.

See Also

shFILE()

set.sys.path(), wrap.source()

Examples

Run this code
FILE1.R <- tempfile(fileext = ".R")
this.path:::.write.code({
    this.path:::.withAutoprint({
        cat(sQuote(this.path::sys.path(verbose = TRUE, default = {
            stop("since the executing script's path will be found,\n",
                " 'default' will not be evaluated, so this error\n",
                " will not be thrown! use this to your advantage to\n",
                " do arbitrary things only if the executing script\n",
                " does not exist")
        })), "\n\n")
    }, spaced = TRUE, verbose = FALSE, width.cutoff = 60L,
       prompt = Sys.getenv("R_PROMPT"), continue = Sys.getenv("R_CONTINUE"))
}, FILE1.R)


oenv <- this.path:::.envvars(R_PROMPT   = "FILE1.R> ",
                             R_CONTINUE = "FILE1.R+ ")


## 'sys.path()' works with 'source()'
source(FILE1.R, verbose = FALSE)


## 'sys.path()' works with 'sys.source()'
sys.source(FILE1.R, envir = environment())


## 'sys.path()' works with 'debugSource()' in 'RStudio'
if (.Platform$GUI == "RStudio")
    get("debugSource", "tools:rstudio", inherits = FALSE)(FILE1.R)


## 'sys.path()' works with 'testthat::source_file()'
if (requireNamespace("testthat"))
    testthat::source_file(FILE1.R, chdir = FALSE, wrap = FALSE)


## 'sys.path()' works with 'knitr::knit()'
if (requireNamespace("knitr")) {
    FILE2.Rmd <- tempfile(fileext = ".Rmd")
    FILE3.md <- tempfile(fileext = ".md")
    writeLines(c(
        "```{r}",
        ## same expression as above
        deparse(parse(FILE1.R)[[c(1L, 2L, 2L)]]),
        "```"
    ), FILE2.Rmd)


    # knitr::knit(FILE2.Rmd, output = FILE3.md, quiet = FALSE)
    ## the above does not work when using the 'Run examples' button in
    ## the HTML documentation. 'package:knitr' cannot knit a document
    ## inside another document, pretty embarrassing oversight, so we
    ## have to launch a new R session and knit the document from there
    FILE4.R <- tempfile(fileext = ".R")
    this.path:::.write.code(bquote({
        knitr::knit(.(FILE2.Rmd), output = .(FILE3.md), quiet = TRUE)
    }), FILE4.R)
    this.path:::.Rscript(
        c("--default-packages=NULL", "--vanilla", FILE4.R),
        show.command = FALSE
    )
    unlink(FILE4.R)


    this.path:::.cat.file(FILE2.Rmd, number.nonblank = TRUE,
        squeeze.blank = TRUE, show.tabs = TRUE,
        show.command = TRUE)
    this.path:::.cat.file(FILE3.md, number.nonblank = TRUE,
        squeeze.blank = TRUE, show.tabs = TRUE,
        show.command = TRUE)
    unlink(c(FILE3.md, FILE2.Rmd))
}


## 'sys.path()' works with 'compiler::loadcmp()'
if (requireNamespace("compiler")) {
    FILE2.Rc <- tempfile(fileext = ".Rc")
    compiler::cmpfile(FILE1.R, FILE2.Rc)
    oenv2 <- this.path:::.envvars(R_PROMPT   = "FILE2.Rc> ",
                                  R_CONTINUE = "FILE2.Rc+ ")
    compiler::loadcmp(FILE2.Rc)
    this.path:::.envvars(oenv2)
    unlink(FILE2.Rc)
}


## 'sys.path()' works with 'box::use()'
if (requireNamespace("box")) {
    FILE2.R <- tempfile(fileext = ".R")
    this.path:::.write.code(bquote({
        ## we have to use box::set_script_path() because 'package:box'
        ## does not allow us to import a module by its path
        script_path <- box::script_path()
        on.exit(box::set_script_path(script_path))
        box::set_script_path(.(normalizePath(FILE1.R, "/")))
        box::use(module = ./.(as.symbol(this.path::removeext(
            this.path::basename2(FILE1.R)
        ))))
        box::unload(module)
    }), FILE2.R)
    source(FILE2.R, echo = TRUE, spaced = FALSE, verbose = FALSE,
        prompt.echo = "FILE2.R> ", continue.echo = "FILE2.R+ ")
    unlink(FILE2.R)
}


## 'sys.path()' works with 'Rscript'
## it also works with other GUIs but that is
## not possible to show in a simple example
this.path:::.Rscript(c("--default-packages=NULL", "--vanilla", FILE1.R))
this.path:::.envvars(oenv)


## 'sys.path()' also works when 'source()'-ing a URL
## (included tryCatch in case an internet connection is not available)
tryCatch({
    source(paste0("https://raw.githubusercontent.com/ArcadeAntics/",
                  "this.path/main/tests/sys-path-with-urls.R"))
}, condition = this.path:::.cat.condition)


for (expr in c("sys.path()",
               "sys.path(default = NULL)",
               "sys.dir()",
               "sys.dir(default = NULL)",
               "sys.dir(default = getwd())"))
{
    cat("\n\n")
    this.path:::.Rscript(c("--default-packages=this.path",
                           "--vanilla", "-e", expr))
}


## an example from R package 'logr'
this.path::sys.path(verbose = FALSE, default = "script.log",
    else. = function(path) {
        ## replace extension (probably .R) with .log
        this.path::ext(path) <- ".log"
        path
        ## or you could use paste0(this.path::removeext(path), ".log")
    })


unlink(FILE1.R)

Run the code above in your browser using DataLab