실행 스크립트의 경로 결정
같은 디렉토리에있는 foo.R
다른 스크립트를 포함 하는 스크립트 가 있습니다 other.R
.
#!/usr/bin/env Rscript
message("Hello")
source("other.R")
그러나 현재 작업 디렉토리가 무엇이든 관계없이 R
찾고 싶습니다 other.R
.
즉, foo.R
자체 경로를 알아야합니다. 어떻게해야합니까?
여기 에 문제에 대한 간단한 해결책이 있습니다. 이 명령은
script.dir <- dirname(sys.frame(1)$ofile)
현재 스크립트 파일의 경로를 반환합니다. 스크립트가 저장된 후에 작동합니다.
이 commandArgs
함수를 사용하여 Rscript가 전달한 모든 옵션을 실제 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)
other.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"
이것이 내가 dehmann이 찾고 있다고 믿는 것입니다.
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)]])
내가 잊어 버렸기 때문에 어떻게 작동하는지 묻지 마십시오.
R 스크립트의 경로 를 얻는 것으로 부터 의 rakensi 의 대답은 가장 정확하고 정말 훌륭한 IMHO입니다. 그러나 여전히 더미 기능을 통합 한 핵입니다. 다른 사람들이 쉽게 찾을 수 있도록 여기에 인용하고 있습니다.
sourceDir <-getSrcDirectory (함수 (더미) {더미})
이것은 명령문이 배치 된 파일의 디렉토리를 제공합니다 (더미 함수가 정의 된 위치). 그런 다음 작업 direcory를 설정하고 상대 경로를 사용하는 데 사용할 수 있습니다.
setwd(sourceDir)
source("other.R")
또는 절대 경로를 만들려면
source(paste(sourceDir, "/other.R", sep=""))
이것은 나를 위해 작동
library(rstudioapi)
rstudioapi::getActiveDocumentContext()$path
Supressingfire의 답변이 축소 된 변형 :
source_local <- function(fname){
argv <- commandArgs(trailingOnly = FALSE)
base_dir <- dirname(substring(argv[grep("--file=", argv)], 8))
source(paste(base_dir, fname, sep="/"))
}
하나의 모든 것! (-RStudio 콘솔을 처리하도록 2019 년 1 월 1 일 업데이트 됨)
#' 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)
}
}
}
}
}
이것은 나를 위해 작동합니다. 명령 행 인수에서이를 제거하고, 원치 않는 텍스트를 제거하고, dirname을 수행 한 후 마지막으로 전체 경로를 가져옵니다.
args <- commandArgs(trailingOnly = F)
scriptPath <- normalizePath(dirname(sub("^--file=", "", args[grep("^--file=", args)])))
이 질문에 대한 답변을 rprojroot 의 새로운 함수 thisfile()
로 마무리 하고 확장했습니다 . 와 뜨개질에도 작동합니다 knitr
.
Steamer25의 솔루션이 내 목적에 가장 강력 해 보였으므로 마음에 들었습니다. 그러나 RStudio (Windows)에서 디버깅 할 때 경로가 올바르게 설정되지 않습니다. 그 이유는 RStudio에서 중단 점이 설정되어 있으면 파일을 소싱 할 때 스크립트 경로를 약간 다르게 설정하는 대체 "디버그 소스"명령을 사용하기 때문입니다. 다음은 디버깅 할 때 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))
}
}
}
나는이 질문에서 거의 모든 시도 에 R 스크립트의 경로를 얻기 , 현재 스크립트의 패스를 취득 , 현재 .R 파일의 위치 찾기 및 Rstudio에서 소스 파일의 위치로 작업 디렉토리를 설정하기위한 R 명령을 했지만 결국 수동으로 나 자신을 발견 CRAN 테이블 찾아보기
scriptName
도서관
current_filename()
RStudio에서 소싱 할 때와 R 또는 RScript 실행 파일을 통해 호출 할 때 스크립트의 올바른 전체 경로를 반환 하는 함수 를 제공 합니다.
방금 직접 해결했습니다. 스크립트의 이식성을 보장하려면 항상 다음으로 시작하십시오.
wd <- setwd(".")
setwd(wd)
"."때문에 작동합니다. 유닉스 명령 $ PWD와 같이 번역합니다. 이 문자열을 문자 객체에 할당하면 해당 문자 객체를 setwd ()에 삽입 할 수 있으며, Presto 코드는 기계의 위치 나 파일 구조의 위치에 관계없이 항상 현재 디렉토리를 작업 디렉토리로 실행합니다. 위치. (추가 보너스 : wd 객체는 file.path () (예 : file.path (wd, "output_directory")와 함께 사용하여 명명 된 디렉토리로 이어지는 파일 경로에 관계없이 표준 출력 디렉토리를 만들 수 있습니다. 이를 위해서는이 방법으로 참조하기 전에 새 디렉토리를 만들어야하지만 wd 객체로도 도움이 될 수 있습니다.
또는 다음 코드는 똑같은 작업을 수행합니다.
wd <- getwd()
setwd(wd)
또는 객체에 파일 경로가 필요하지 않은 경우 간단히 다음을 수행 할 수 있습니다.
setwd(".")
r 스크립트를 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 모듈로 이미 작성된 기능을 제공하므로 "스크립트 경로 가져 오기"기능을 복사하여 모든 스크립트에 붙여 넣을 필요는 없습니다. 당신은 쓰기.
참조 findSourceTraceback()
의 R.utils의 , 포장하는
모든 호출 프레임에서 source ()에 의해 생성 된 모든 'srcfile'객체를 찾습니다. 이를 통해 source ()가 현재 어떤 파일을 스크립팅했는지 확인할 수 있습니다.
내 스크립트가 심볼릭 링크 디렉토리에서 작동 할 때 위의 구현에 문제가 있거나 적어도 위의 솔루션이 효과가 없다고 생각합니다. @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
은 스크립트의 정규화 된 경로를 포함 하는 변수 를 제공합니다 . 소스의 사용을 고백하기 때문에 때때로 Rscript를 호출하고 --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를 사용하십시오.
#!/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='/'))
Steamer25의 접근 방식은 작동하지만 경로에 공백이없는 경우에만 작동합니다. macOS에서는 적어도 for 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처럼 else 블록을 확장 할 수 있습니다.
R에는 '$ 0'유형 구조가 없습니다! R로 작성된 bash 스크립트에 대한 system () 호출로이를 수행 할 수 있습니다.
write.table(c("readlink -e $0"), file="scriptpath.sh",col=F, row=F, quote=F)
thisscript <- system("sh scriptpath.sh", intern = TRUE)
그런 다음 다른 scriptpath.sh 이름을 분리하십시오.
splitstr <- rev(strsplit(thisscript, "\\/")[[1]])
otherscript <- paste0(paste(rev(splitstr[2:length(splitstr)]),collapse="/"),"/other.R")
스크립트가 아닌 foo.R
경로 위치를 알고 있다면, 모든 source
공통 경로 를 항상 참조하도록 코드를 변경할 수 있다면 root
다음과 같은 도움이 될 것입니다.
주어진
/app/deeply/nested/foo.R
/app/other.R
이 작동합니다
#!/usr/bin/env Rscript
library(here)
source(here("other.R"))
프로젝트 루트를 정의하는 방법 은 https://rprojroot.r-lib.org/ 를 참조 하십시오 .
호출 스택을 보면 실행중인 각 스크립트의 파일 경로를 얻을 수 있습니다. 가장 유용한 두 가지는 아마도 현재 실행중인 스크립트이거나 소스가 될 첫 번째 스크립트 일 것입니다 (입력).
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) ))()
참고 URL : https://stackoverflow.com/questions/1815606/determine-path-of-the-executing-script
'Programing' 카테고리의 다른 글
복사 초기화와 직접 초기화간에 차이가 있습니까? (0) | 2020.04.17 |
---|---|
System.currentTimeMillis () vs. 새로운 Date () vs. Calendar.getInstance (). getTime () (0) | 2020.04.17 |
Java, "for each"루프에서 현재 색인 / 키를 얻는 방법 (0) | 2020.04.17 |
WebView의 Android 호출 JavaScript 함수 (0) | 2020.04.17 |
Oracle 데이터베이스에 부울 유형이 있습니까? (0) | 2020.04.17 |