bestsource

실행 중인 스크립트의 경로 결정

bestsource 2023. 6. 28. 21:53
반응형

실행 중인 스크립트의 경로 결정

는 라는대본있습다라는 .foo.R에는 다른 " 다스트를포다니함합립크른▁another"가 포함되어 .other.R다음과 같은 디렉토리에 있습니다.

#!/usr/bin/env Rscript
message("Hello")
source("other.R")

하지만 나는 원합니다.R을 발견하기 위해other.R현재 작업 디렉토리에 상관없이.

다른말하면로,하면,foo.R자신의 길을 알아야 합니다.내가 어떻게 그럴 수 있을까?

여기 문제에 대한 간단한 해결책이 있습니다.다음 명령:

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

현재 스크립트 파일의 경로를 반환합니다.스크립트가 저장된 후에 작동합니다.

당신은 할 수 .commandArgs에 의해 R 입니다.--file=스크립트가 경로에서 시작되었거나 전체 경로로 시작된 경우script.name는 아는로시것다니로 할 것입니다.'/'그렇지 않으면, 그것은 다음과 상대적이어야 합니다.cwd그리고 두 경로를 결합하여 전체 경로를 얻을 수 있습니다.

편집: 다음만 필요한 것처럼 들립니다.script.name경로의 최종 구성 요소를 벗겨냅니다.내가 불필요한 것들을 제거했습니다.cwd()샘플을 채취하고 메인 스크립트를 정리하고 게시했습니다.other.R이 스크립트를 저장하면 됩니다.other.R한 디렉토리인 같은디리에스작성다니합크를트로 작성합니다.chmod +x기본 스크립트를 실행합니다.

main.R:

#!/usr/bin/env Rscript
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)
other.name <- file.path(script.basename, "other.R")
print(paste("Sourcing",other.name,"from",script.name))
source(other.name)

기타.R:

print("hello")

출력:

burner@firefighter:~$ main.R
[1] "Sourcing /home/burner/bin/other.R from /home/burner/bin/main.R"
[1] "hello"
burner@firefighter:~$ bin/main.R
[1] "Sourcing bin/other.R from bin/main.R"
[1] "hello"
burner@firefighter:~$ cd bin
burner@firefighter:~/bin$ main.R
[1] "Sourcing ./other.R from ./main.R"
[1] "hello"

이것이 데만이 찾고 있는 것이라고 생각합니다.

R 콘솔에서 '소스'할 때 Suppressingfire의 솔루션이 작동하지 않았습니다.
나는 Rscript를 사용할 때 Hadley의 해결책을 얻을 수 없었습니다.

두 세계의 장점?

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))
        }
}
frame_files <- lapply(sys.frames(), function(x) x$ofile)
frame_files <- Filter(Negate(is.null), frame_files)
PATH <- dirname(frame_files[[length(frame_files)]])

하지만 어떻게 작동하는지 묻지 마세요, 왜냐하면 저는 잊어버렸으니까요 :/

이것은 나에게 효과가 있습니다.

library(rstudioapi)    
rstudioapi::getActiveDocumentContext()$path

R 스크립트의 경로를 얻는 것에서 나온 라켄시의 대답은 가장 정확하고 정말 훌륭한 IMHO입니다.하지만, 그것은 여전히 더미 기능을 통합하는 해킹입니다.다른 사람들이 쉽게 찾을 수 있도록 여기에 인용합니다.

sourceDir <- getSrcDirectory(function(dummy) {dummy})

이것은 문이 배치된 파일의 디렉토리(더미 함수가 정의된 위치)를 제공합니다.그런 다음 작업 디렉터리를 설정하고 관련 경로를 사용할 수 있습니다.

setwd(sourceDir)
source("other.R")

또는 절대 경로를 생성합니다.

 source(paste(sourceDir, "/other.R", sep=""))

Cran과 GitHub에서 사용할 수 있는 이 .path라는 패키지를 만들었습니다.현재 버전은 1.4.0(2023-04-18)이며 다음 사이트에서 확인할 수 있습니다.

https://CRAN.R-project.org/package=this.path

https://github.com/ArcadeAntics/this.path

CRAN에서 설치:

utils::install.packages("this.path")

또는 GitHub에서 개발 버전을 설치합니다.

utils::install.packages("this.path",
    repos = "https://raw.githubusercontent.com/ArcadeAntics/PACKAGES")

그런 다음 다음 다음과 같이 입력합니다.

this.path::this.path()

또는

library(this.path)
this.path()

아래 답변은 위에서 사용할 수 있는 최신 버전보다 기능이 다소 떨어지지만 참고용으로 보관된 제 원래 답변입니다.향상된 기능은 다음과 같습니다.

  • 더 많은 GUI와의 호환성: Windows의 'Rgui', 'VScode' 및 'Jupiter'
  • 패키지와의 호환성 테스트, knitr, 컴파일러박스, 특히testthat::source_file(),knitr::knit(),compiler::loadcmp(),그리고.box::use()
  • Unix-like에서 셸에서 R 스크립트를 실행할 때 공백이 있는 파일 이름 처리
  • 하는 두 를 모두 합니다.-f FILE그리고.--file=FILE)
  • 할 때 를 올바르게 정규화합니다.source() 의으로로(chdir = TRUE)
  • "URI"를 사용하여 source()를 들면source("file:///path/to/file")그리고.source("file:///C:/path/to/file")
  • 문대 처리 개선결 내의 문자열 source()
  • 경로 리처이에서 처리source()즉, 다음과 같습니다.
source("https://host/path/to/file")

한다면this.path()파일 내에서 사용되면 반환됩니다."https://host/path/to/file" " 은또한다에시작는로하 URL"로됩니다."http://","ftp://",그리고."ftps://"예를 들어, 다음을 시도합니다.

source("https://raw.githubusercontent.com/ArcadeAntics/this.path/main/tests/this.path_w_URLs.R")
  • 에는 기능이 되어 있습니다.here()/ /this.proj()와비한과 한.here::here()스크립트의 / 스크립트의 파일 하는 경우 //실행 스크립트의 프로젝트 경로를 지정합니다.
  • 하는 처음에적환내에정경로저장this.path()는 스크립트 내에서 호출되므로 동일한 스크립트 내에서 이후 시간을 더 빠르게 사용할 수 있으며 작업 디렉토리와 무관합니다.은 즉을 합니다.setwd()더 이상 부서지지 않을 것입니다.this.path() 경우)setwd()에 대한 첫 번째 호출 에 사용됩니다.this.path()해당 스크립트 내)

원본 답변:

제 대답은 제리 T의 대답을 개선한 것입니다.제가 발견한 문제는 그들이 추측하고 있다는 것입니다.source()변수인지 확인하여 통화가 이루어졌습니다.ofile스택의 첫 번째 프레임에 있습니다.이것은 중첩된 소스 호출이나 전역이 아닌 환경에서 만들어진 소스 호출에서는 작동하지 않습니다.추가적으로, 주문이 잘못되었습니다.셸 인수를 확인하기 전에 소스 호출을 찾아야 합니다.제 솔루션은 다음과 같습니다.

this.path <- function (verbose = getOption("verbose"))
{
    ## loop through functions that lead here from most recent to
    ## earliest looking for an appropriate source call (a call to
    ## function source / / sys.source / / debugSource in RStudio)
    ##
    ## an appropriate source call is one in which the file argument has
    ## been evaluated (forced)
    ##
    ## for example, `source(this.path())` is an inappropriate source
    ## call. the argument 'file' is stored as a promise containing the
    ## expression "this.path()". when the value of 'file' is requested,
    ## the expression is evaluated at which time there should be two
    ## functions on the calling stack being 'source' and 'this.path'.
    ## clearly, you don't want to request the 'file' argument from that
    ## source call because the value of 'file' is under evaluation
    ## right now! the trick is to ask if 'file' has already been
    ## evaluated, the easiest way of which is to ask if a variable
    ## exists, one which is only created after the expression is
    ## necessarily evaluated.
    ##
    ## if that variable does exist, then argument 'file' has been
    ## forced and the source call is deemed appropriate. For 'source',
    ## the filename we want is the variable 'ofile' from that
    ## function's evaluation environment. For 'sys.source', the
    ## filename we want is the variable 'file' from that function's
    ## evaluation environment.
    ##
    ## if that variable does NOT exist, then argument 'file' hasn't
    ## been forced and the source call is deemed inappropriate. the
    ## 'for' loop moves to the next function up the calling stack
    ##
    ## unfortunately, there is no way to check the argument 'fileName'
    ## has been forced for 'debugSource' since all the work is done
    ## internally in C. Instead, we have to use a 'tryCatch' statement.
    ## When we ask for an object by name using 'get', R is capable of
    ## realizing if a variable is asking for its own definition (a
    ## recursive promise). The exact error is "promise already under
    ## evaluation" which indicates that the promise evaluation is
    ## requesting its own value. So we use the 'tryCatch' to get the
    ## argument 'fileName' from the evaluation environment of
    ## 'debugSource', and if it does not raise an error, then we are
    ## safe to return that value. If not, the condition returns false
    ## and the 'for' loop moves to the next function up the calling
    ## stack


    debugSource <- if (.Platform$GUI == "RStudio")
        get("debugSource", "tools:rstudio", inherits = FALSE)
    for (n in seq.int(to = 1L, by = -1L, length.out = sys.nframe() - 1L)) {
        if (identical(sys.function(n), source) &&
            exists("ofile", envir = sys.frame(n), inherits = FALSE))
        {
            path <- get("ofile", envir = sys.frame(n), inherits = FALSE)
            if (!is.character(path))
                path <- summary.connection(path)$description
            if (verbose)
                cat("Source: call to function source\n")
            return(normalizePath(path, "/", TRUE))
        }
        else if (identical(sys.function(n), sys.source) &&
                 exists("exprs", envir = sys.frame(n), inherits = FALSE))
        {
            path <- get("file", envir = sys.frame(n), inherits = FALSE)
            if (verbose)
                cat("Source: call to function sys.source\n")
            return(normalizePath(path, "/", TRUE))
        }
        else if (identical(sys.function(n), debugSource) &&
                 tryCatch({
                     path <- get("fileName", envir = sys.frame(n), inherits = FALSE)
                     TRUE
                 }, error = function(c) FALSE))
        {
            if (verbose)
                cat("Source: call to function debugSource in RStudio\n")
            return(normalizePath(path, "/", TRUE))
        }
    }


    ## no appropriate source call was found up the calling stack


    ## running from RStudio
    if (.Platform$GUI == "RStudio") {


        ## ".rs.api.getSourceEditorContext" from "tools:rstudio"
        ## returns a list of information about the document open in the
        ## current tab
        ##
        ## element 'path' is a character string, the document's path


        context <- get(".rs.api.getSourceEditorContext",
            "tools:rstudio", inherits = FALSE)()
        if (is.null(context))
            stop("'this.path' used in an inappropriate fashion\n",
                 "* no appropriate source call was found up the calling stack\n",
                 "* R is being run from RStudio with no documents open\n",
                 "  (or source document has no path)")


        path <- context[["path"]]
        if (nzchar(path)) {
            Encoding(path) <- "UTF-8"
            if (verbose)
                cat("Source: document in RStudio\n")
            return(normalizePath(path, "/", TRUE))
        }
        else stop("'this.path' used in an inappropriate fashion\n",
                  "* no appropriate source call was found up the calling stack\n",
                  "* document in RStudio does not exist")
    }


    ## running from a shell
    else if (.Platform$OS.type == "windows" && .Platform$GUI == "RTerm" ||  ## on Windows
             .Platform$OS.type == "unix"    && .Platform$GUI == "X11")      ## under Unix-alikes
    {


        argv <- commandArgs()
        ## remove all trailing arguments
        m <- match("--args", argv, 0L)
        if (m)
            argv <- argv[seq_len(m)]
        argv <- argv[-1L]


        ## get all arguments starting with "--file="
        FILE <- argv[startsWith(argv, "--file=")]
        ## remove "--file=" from the start of each string
        FILE <- substring(FILE, 8L)
        ## remove strings "-"
        FILE <- FILE[FILE != "-"]
        n <- length(FILE)
        if (n) {
            FILE <- FILE[[n]]
            if (verbose)
                cat("Source: shell argument 'FILE'\n")
            return(normalizePath(FILE, "/", TRUE))
        } else {
            stop("'this.path' used in an inappropriate fashion\n",
                 "* no appropriate source call was found up the calling stack\n",
                 "* R is being run from a shell where argument 'FILE' is missing")
        }
    }


    ## running from RGui on Windows
    else if (.Platform$OS.type == "windows" && .Platform$GUI == "Rgui") {
        stop("'this.path' used in an inappropriate fashion\n",
             "* no appropriate source call was found up the calling stack\n",
             "* R is being run from Rgui which is currently unimplemented",
             "  consider using RStudio until such a time when this is implemented")
    }


    ## running from RGui on macOS
    else if (.Platform$OS.type == "unix" && .Platform$GUI == "AQUA") {
        stop("'this.path' used in an inappropriate fashion\n",
             "* no appropriate source call was found up the calling stack\n",
             "* R is being run from AQUA which is currently unimplemented\n",
             "  consider using RStudio until such a time when this is implemented")
    }


    ## otherwise
    else stop("'this.path' used in an inappropriate fashion\n",
              "* no appropriate source call was found up the calling stack\n",
              "* R is being run in an unrecognized manner")
}

나의 올인원! (--2019년 1월 9일 RStudio Console을 처리하기 위해 업데이트됨)

#' current script file (in full path)
#' @description current script file (in full path)
#' @examples
#' works with Rscript, source() or in RStudio Run selection, RStudio Console
#' @export
ez.csf <- function() {
    # http://stackoverflow.com/a/32016824/2292993
    cmdArgs = commandArgs(trailingOnly = FALSE)
    needle = "--file="
    match = grep(needle, cmdArgs)
    if (length(match) > 0) {
        # Rscript via command line
        return(normalizePath(sub(needle, "", cmdArgs[match])))
    } else {
        ls_vars = ls(sys.frames()[[1]])
        if ("fileName" %in% ls_vars) {
            # Source'd via RStudio
            return(normalizePath(sys.frames()[[1]]$fileName))
        } else {
            if (!is.null(sys.frames()[[1]]$ofile)) {
            # Source'd via R console
            return(normalizePath(sys.frames()[[1]]$ofile))
            } else {
                # RStudio Run Selection
                # http://stackoverflow.com/a/35842176/2292993
                pth = rstudioapi::getActiveDocumentContext()$path
                if (pth!='') {
                    return(normalizePath(pth))
                } else {
                    # RStudio Console
                    tryCatch({
                            pth = rstudioapi::getSourceEditorContext()$path
                            pth = normalizePath(pth)
                        }, error = function(e) {
                            # normalizePath('') issues warning/error
                            pth = ''
                        }
                    )
                    return(pth)
                }
            }
        }
    }
}

Suppressing Fire의 슬림한 변형 답변:

source_local <- function(fname){
    argv <- commandArgs(trailingOnly = FALSE)
    base_dir <- dirname(substring(argv[grep("--file=", argv)], 8))
    source(paste(base_dir, fname, sep="/"))
}

이것은 나에게 효과가 있습니다.명령줄 인수에서 이를 제거하고 원하지 않는 텍스트를 제거한 후 dirname을 수행하면 마지막으로 전체 경로를 얻을 수 있습니다.

args <- commandArgs(trailingOnly = F)  
scriptPath <- normalizePath(dirname(sub("^--file=", "", args[grep("^--file=", args)])))

는 이 기능으로 했습니다.thisfile()rprojroot에서.또한 뜨개질에도 사용됩니다.knitr.

R 스크립트의 경로 가져오기, 현재 스크립트의 경로 가져오기, 현재 .R 파일의 위치 찾기, R studio에서 작업 디렉토리를 소스 파일 위치로 설정하기 위한 R 명령 등 이 질문의 거의 모든 것을 시도했지만, 결국 제가 수동으로 CRAN 테이블을 탐색하는 것을 발견했습니다.

scriptName 도서관

▁provides다▁which를 제공합니다.current_filename()함수 - RStudio에서 소싱할 때 및 R 또는 RScript 실행 파일을 통해 호출할 때 스크립트의 적절한 전체 경로를 반환합니다.

제 목적에 가장 적합한 것 같아서 25번 찜통의 솔루션이 마음에 들었습니다.그러나 RStudio(윈도우)에서 디버깅할 때 경로가 제대로 설정되지 않습니다.RStudio에서 중단점이 설정된 경우 파일을 원본으로 하면 스크립트 경로를 약간 다르게 설정하는 대체 "debug source" 명령이 사용되기 때문입니다.다음은 현재 사용 중인 최종 버전으로 디버깅 시 RStudio 내에서 이 대체 동작을 설명합니다.

# @return full path to this script
get_script_path <- function() {
    cmdArgs = commandArgs(trailingOnly = FALSE)
    needle = "--file="
    match = grep(needle, cmdArgs)
    if (length(match) > 0) {
        # Rscript
        return(normalizePath(sub(needle, "", cmdArgs[match])))
    } else {
        ls_vars = ls(sys.frames()[[1]])
        if ("fileName" %in% ls_vars) {
            # Source'd via RStudio
            return(normalizePath(sys.frames()[[1]]$fileName)) 
        } else {
            # Source'd via R console
            return(normalizePath(sys.frames()[[1]]$ofile))
        }
    }
}

방금 제가 해결했습니다.스크립트의 이동성을 보장하려면 항상 다음과 같이 시작합니다.

wd <- setwd(".")
setwd(wd)

"."가 유닉스 명령 $PWD처럼 번역되기 때문에 작동합니다.이 문자열을 문자 개체에 할당하면 해당 문자 개체를 setwd()에 삽입할 수 있으며 Presto 코드는 누구의 컴퓨터에 있든 파일 구조의 위치에 상관없이 항상 현재 디렉터리를 작업 디렉터리로 사용하여 실행됩니다. (추가 보너스:wd 개체를 file.path()(즉, file.path(wd, "output_directory")와 함께 사용하여 명명된 디렉토리로 이어지는 파일 경로에 관계없이 표준 출력 디렉토리를 만들 수 있습니다.이렇게 하려면 디렉터리를 이렇게 참조하기 전에 새 디렉터리를 만들어야 하지만 wd 개체로도 도움이 될 수 있습니다.

또는 다음 코드가 동일한 작업을 수행합니다.

wd <- getwd()
setwd(wd)

또는 개체에 파일 경로가 필요하지 않은 경우 다음과 같이 간단히 수행할 수 있습니다.

setwd(".")

저도 이런 문제가 있었는데, 위의 해결책들 중 어떤 것도 저에게 효과가 없었습니다.아마도 그것과 함께.source또는 그런 것들, 하지만 충분히 명확하지 않았습니다.

저는 이것이 저에게 우아한 해결책이라고 생각했습니다.

paste0(gsub("\\", "/", fileSnapshot()$path, fixed=TRUE),"/")

그 점에서 중요한 것은fileSnapshot()파일에 대한 많은 정보를 제공합니다.8개 요소의 목록을 반환합니다.을 때.path가 리트요소경다같반이환됩니다음과로는스서와 함께 됩니다.\\구분자로, 그래서 나머지 코드는 단지 그것을 바꾸는 것입니다.

이것이 도움이 되길 바랍니다.

다음과 같이 스크립트를 bash 스크립트로 래핑하고 스크립트의 경로를 bash 변수로 검색할 수 있습니다.

#!/bin/bash
     # [environment variables can be set here]
     path_to_script=$(dirname $0)

     R --slave<<EOF
        source("$path_to_script/other.R")

     EOF

저는 이 접근 방식이 좋습니다.

this.file <- sys.frame(tail(grep('source',sys.calls()),n=1))$ofile
this.dir <- dirname(this.file)

는 getopt를 제공합니다.get_Rscript_filename함수는 여기에 제시된 것과 동일한 솔루션을 사용하지만 이미 표준 R 모듈에 작성되었으므로 "스크립트 경로 가져오기" 함수를 복사하여 모든 스크립트에 붙여넣을 필요가 없습니다.

대보다는.foo.R위치를 할 수 모든 을 참조할 수 . 항상 모두 참조하도록 코드를 변경할 수 있다면source에서 온 'droot그러면 큰 도움이 될 수 있습니다.

정해진

  • /app/deeply/nested/foo.R
  • /app/other.R

이것은 효과가 있을 것입니다.

#!/usr/bin/env Rscript
library(here)
source(here("other.R"))

프로젝트 루트를 정의하는 방법은 https://rprojroot.r-lib.org/ 을 참조하십시오.

제 스크립트가 연결된 디렉토리에서 작동하기 때문에 위의 구현에 문제가 있었습니다. 또는 적어도 그 때문에 위의 솔루션이 저에게 적합하지 않은 것 같습니다.@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)

저는 @steamer25의 접근 방식의 변형을 사용할 것입니다.요점은 Rscript를 통해 세션이 시작되었을 때에도 마지막 소스 스크립트를 얻는 것을 선호한다는 것입니다.때 " 에파포된다스제변다공니합를수은펫니음"를 제공합니다.thisScript스크립트의 정규화된 경로를 포함합니다.저는을 고백하기 와 와source'ing의 (ab)에 합니다.--file인수는 다른 스크립트를 소스로 하는 다른 스크립트를 소스로 합니다.언젠가 나는 나의 지저분한 코드를 패키지로 바꾸는 데 투자할 것입니다.

thisScript <- (function() {
  lastScriptSourced <- tail(unlist(lapply(sys.frames(), function(env) env$ofile)), 1)

  if (is.null(lastScriptSourced)) {
    # No script sourced, checking invocation through Rscript
    cmdArgs <- commandArgs(trailingOnly = FALSE)
    needle <- "--file="
    match <- grep(needle, cmdArgs)
    if (length(match) > 0) {
      return(normalizePath(sub(needle, "", cmdArgs[match]), winslash=.Platform$file.sep, mustWork=TRUE))
    }
  } else {
    # 'source'd via R console
    return(normalizePath(lastScriptSourced, winslash=.Platform$file.sep, mustWork=TRUE))
  }
})()

99%의 사례를 단순하게 사용할 수 있습니다.

sys.calls()[[1]] [[2]]

스크립트가 첫 번째 인수가 아닌 미친 호출에는 작동하지 않습니다.source(some args, file="myscript")이런 멋진 경우에는 @hadley's를 사용합니다.

Steamer25의 접근은 경로에 공백이 없을 때만 가능합니다. macOS에서는cmdArgs[match]와 같은 것을 반환합니다./base/some~+~dir~+~with~+~whitespace/위해서/base/some\ dir\ with\ whitespace/.

저는 반품하기 전에 "~~+~"를 단순한 공백으로 교체하여 이 문제를 해결했습니다.

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

분명히 당신은 aprstar가 했던 것처럼 여전히 다른 블록을 확장할 수 있습니다.

호출 스택을 보면 실행 중인 각 스크립트의 파일 경로를 얻을 수 있습니다. 가장 유용한 두 가지는 현재 실행 중인 스크립트이거나 소스가 될 첫 번째 스크립트(엔트리)일 것입니다.

script.dir.executing = (function() return( if(length(sys.parents())==1) getwd() else dirname( Filter(is.character,lapply(rev(sys.frames()),function(x) x$ofile))[[1]] ) ))()

script.dir.entry = (function() return( if(length(sys.parents())==1) getwd() else dirname(sys.frame(1)$ofile) ))()

해결책은 2016년에 도착했습니다.작가 Sahil Seth에게 많은 감사를 드립니다!

키지funrCRANgithub에서 기능을 제공합니다.sys.script()현재 스크립트에 대한 전체 경로를 가져옵니다.그것은 심지어 비슷한 SO 게시물을 참조합니다.

따라서 솔루션은 다음과 같습니다.

내 대본R:

#!/usr/bin/env Rscript
f  <-  funr::sys.script()
show(f)

다음 명령을 실행합니다.

user@somewhere:/home$ Rscript myscript.R

명령행에서 출력됩니다. 예:

"/home/path/to/myscript.R"

콘솔에

» findSourceTraceback()R.utils 패키지의.

모든 호출 프레임에서 source()에 의해 생성된 모든 'srcfile' 개체를 찾습니다.이를 통해 현재 소스()에 의해 스크립팅된 파일을 확인할 수 있습니다.

#!/usr/bin/env Rscript
print("Hello")

# sad workaround but works :(
programDir <- dirname(sys.frame(1)$ofile)
source(paste(programDir,"other.R",sep='/'))
source(paste(programDir,"other-than-other.R",sep='/'))

R에 '$0' 유형 구조가 없다는 것이 놀랍습니다! R:로 작성된 bash 스크립트에 대한 시스템() 호출로 이를 수행할 수 있습니다.

write.table(c("readlink -e $0"), file="scriptpath.sh",col=F, row=F, quote=F)
thisscript <- system("sh scriptpath.sh", intern = TRUE)

그런 다음 scriptpath.sh 이름을 다른 이름으로 나누면 됩니다.r

splitstr <- rev(strsplit(thisscript, "\\/")[[1]])
otherscript <- paste0(paste(rev(splitstr[2:length(splitstr)]),collapse="/"),"/other.R")

저는 HPC 클러스터 환경에서 일합니다.운영 환경과는 다른 위치에서 코드를 개발합니다.개발하는 동안, 저는 보통 (RStudio를 사용하지 않고) 명령줄에서 R을 대화형으로 호출합니다.많이 있습니다.source("foo.R")진행 중인

프로덕션 실행 중에는 대개 다른 매개 변수를 시도하고 각 매개 변수 집합을 별도의 디렉터리에 실행하는 bash 스크립트를 작성합니다.bash 스크립트는 워크로드 관리자(SLURM)를 활용합니다.이러한 환경에서 환경 변수를 설정하는 것은 사소한 일입니다.이러한 점을 고려하여 아래 솔루션이 저에게 가장 적합합니다.

기타

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 R 에서 실행한다면./path/to/R/code 하다

> source("foo.R")

대화형셸에서 되지 않는 /path/to/R/code 변수를 합니다.R_SRC먼저, 그리고 나서 전화하세요.Rscript

$ export R_SRC=/path/to/R/code/
$ Rscript /path/to/R/code/foo.R

답변을 검사를 , 이유로든) 할 수 .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')

언급URL : https://stackoverflow.com/questions/1815606/determine-path-of-the-executing-script

반응형