같은 디렉토리에있는 foo.R
다른 스크립트를 포함 하는 스크립트 가 있습니다 other.R
.
#!/usr/bin/env Rscript
message("Hello")
source("other.R")
그러나 현재 작업 디렉토리가 무엇이든 관계없이 R
찾고 싶습니다 other.R
.
즉, foo.R
자체 경로를 알아야합니다. 어떻게해야합니까?
같은 디렉토리에있는 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)
현재 스크립트 파일의 경로를 반환합니다. 스크립트가 저장된 후에 작동합니다.
dirname(sys.frame(1)$ofile)
는 Rstudio에서 직접 실행하려고 할 때 발생합니다 . source ( "other.R")를 사용하여 스크립트를 실행하고 dirname(sys.frame(1)$ofile)
내부에 있으면 정상적으로 작동합니다 "other.R"
.
NULL
서버에 넣을 때 젤 을 뿌립니다. R을 사용할 때
이 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이 찾고 있다고 믿는 것입니다.
source
OP가 원한다고 생각 한대로 기술이 작동하지 않기 때문에 다운 모드가 되었지만 요구 사항을 잘못 읽었을 수 있습니다 . 그러나 나는 다운 모드를 풀 수 없습니다 :( 죄송합니다!
other.name <- file.path(script.basename, "other.R")
commandArgs(trailingOnly = FALSE)
반짝이는 응용 프로그램에서 server.R 내부 를 실행하려고 하면 [1] "RStudio" "--interactive"
. 호출 된 디렉토리에 대한 정보가 없습니다.
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))
}
}
Rscript
과 source()
R 모두에서 작동하기 때문에 이것을 좋아합니다 normalizePath()
. 두 버전 모두에서 작업 을 수행하는 것이 좋습니다 .
library(base)
데 시간 이 걸렸습니다. lol
source(file.path(dirname(thisFile()), "other.R"))
는 foo.R
입니다. 이것은 나를 위해 작동합니다.
main.R
어떤 소스 helper.R
를 호출 하는지 RStudio I 소스에서 가정하십시오 thisFile()
. main.R
대신 경로를 가져옵니다 helper.R
. 여기 팁이 있습니까?
frame_files <- lapply(sys.frames(), function(x) x$ofile)
frame_files <- Filter(Negate(is.null), frame_files)
PATH <- dirname(frame_files[[length(frame_files)]])
내가 잊어 버렸기 때문에 어떻게 작동하는지 묻지 마십시오.
sys.frames
호출 스택의 환경을 반환하므로 함수에서 호출 할 때만 의미가 있습니다. 예를 들어 foo <- function() {bar <- function() print(sys.frames()); bar()}; foo()
. 환경에 ofile
멤버 가 없기 때문에 @hadley의 코드를 알 수 없습니다 .
source("~/code/test.r")
, PATH
로 설정됩니다 ~/desktop
. 최상위 수준에서 평가하면 NULL을 반환합니다.
x$ofile
정의되지 않았으므로 frame_files
비어 있습니다.
라켄시 의 답R 스크립트의 경로 를 얻는 부터 가장 정확하고 정말 훌륭한 IMHO입니다. 그러나 여전히 더미 기능을 통합 한 핵입니다. 다른 사람들이 쉽게 찾을 수 있도록 여기에 인용하고 있습니다.
sourceDir <-getSrcDirectory (함수 (더미) {더미})
이것은 명령문이 배치 된 파일의 디렉토리를 제공합니다 (더미 함수가 정의 된 위치). 그런 다음 작업 direcory를 설정하고 상대 경로를 사용하는 데 사용할 수 있습니다.
setwd(sourceDir)
source("other.R")
또는 절대 경로를 만들려면
source(paste(sourceDir, "/other.R", sep=""))
sourceDir
비어있었습니다.
character(0)
있습니다. 제안?
하나의 모든 것! (-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)
}
}
}
}
}
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 실행 파일을 통해 호출 할 때 스크립트의 올바른 전체 경로를 반환 하는 기능 을 제공 합니다.
Package ‘scriptName’ was removed from the CRAN repository.
-지금 뭐야? : o
나는 또한이 문제가 있었고 위의 해결책 중 어느 것도 나를 위해 일하지 않았다. 어쩌면 그와 source
같은 것들이지만 아마도 명확하지 않았습니다.
나는 이것이 나에게 우아하다는 것을 발견했다.
paste0(gsub("\\", "/", fileSnapshot()$path, fixed=TRUE),"/")
중요한 점 fileSnapshot()
은 파일에 대한 많은 정보를 제공 한다는 것입니다 . 8 개의 요소 목록을 반환합니다. path
목록 요소로 선택 하면 경로가 \\
구분 기호로 반환 되므로 나머지 코드는 경로 를 변경하는 것입니다.
이게 도움이 되길 바란다.
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)
방금 직접 해결했습니다. 스크립트의 이식성을 보장하려면 항상 다음으로 시작하십시오.
wd <- setwd(".")
setwd(wd)
"."때문에 작동합니다. 유닉스 명령 $ PWD와 같이 번역합니다. 이 문자열을 문자 객체에 할당하면 해당 문자 객체를 setwd () 및 Presto에 삽입 할 수 있습니다 코드는 기계의 위치 나 파일 구조의 위치에 관계없이 항상 현재 디렉토리를 작업 디렉토리로 실행합니다. 위치. (추가 보너스 : wd 객체는 file.path () (예 : file.path (wd, "output_directory")와 함께 사용하여 명명 된 디렉토리로 이어지는 파일 경로에 관계없이 표준 출력 디렉토리를 만들 수 있습니다. 이를 위해서는이 방법으로 참조하기 전에 새 디렉토리를 만들어야하지만 wd 객체로도 도움이 될 수 있습니다.
또는 다음 코드는 똑같은 작업을 수행합니다.
wd <- getwd()
setwd(wd)
또는 객체에 파일 경로가 필요하지 않은 경우 간단히 다음을 수행 할 수 있습니다.
setwd(".")
getopt 패키지는 get_Rscript_filename
여기에 제시된 것과 동일한 솔루션을 사용하지만 표준 R 모듈로 이미 작성된 기능을 제공하므로 "스크립트 경로 가져 오기"기능을 복사하여 모든 스크립트에 붙여 넣을 필요는 없습니다. 당신은 쓰기.
R -e "library(getopt); testscript.R"
Rscript
.
내 스크립트가 심볼릭 링크 디렉토리에서 작동 할 때 위의 구현에 문제가 있거나 적어도 위의 솔루션이 효과가 없다고 생각합니다. @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))
}
})()
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 블록을 확장 할 수 있습니다.
스크립트 대신 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/ 를 참조 하십시오 .
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")
readLink: illegal option -- e usage: readLink [-FlLnqrsx] [-f format] [-t timefmt] [file ...]
호출 스택을 보면 실행중인 각 스크립트의 파일 경로를 얻을 수 있습니다. 가장 유용한 두 가지는 아마도 현재 실행중인 스크립트이거나 소스가 될 첫 번째 스크립트 일 것입니다.
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) ))()