Xác định đường dẫn của tập lệnh thực thi


255

Tôi có một tập lệnh được gọi foo.Rbao gồm một tập lệnh khác other.R, nằm trong cùng thư mục:

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

Nhưng tôi muốn Rthấy rằng other.Rkhông có vấn đề gì với thư mục làm việc hiện tại.

Nói cách khác, foo.Rcần phải biết con đường riêng của nó. Làm thế nào tôi có thể làm điều đó?


2
Không :( Tôi chưa thấy giải pháp nào thực sự hoạt động. Ngoài cách giải quyết là chỉ cần chuyển thư mục vào hoặc sử dụng biến môi trường.
Frank

3
Điều này sẽ là tuyệt vời để làm cho các kịch bản hoàn toàn di động và thực thi bởi ngay cả R neofites!
Etienne Low-Décarie

4
Có vẻ như tất cả các câu trả lời yêu cầu bạn nhập đường dẫn tại một số điểm (ít nhất là để lấy tệp)! Sẽ thật tuyệt nếu bạn có thể gửi cho ai đó một thư mục nén và chạy bất kỳ tệp tập lệnh R nào trong thư mục đó sẽ đọc và lưu vào thư mục đó.
Etienne Low-Décarie

10
vấn đề duy nhất này thực sự có thể trở thành lý do tại sao tôi hoàn toàn có thể chuyển sang Python
Giacomo

5
@giac_man, tôi cảm thấy R có hàng trăm vấn đề nhỏ như thế này mà tất cả đều gây ra rất khó để làm việc.
Michael Barton

Câu trả lời:


102

Ở đây có một giải pháp đơn giản cho vấn đề. Lệnh này:

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

trả về đường dẫn của tệp script hiện tại. Nó hoạt động sau khi tập lệnh được lưu.


4
Nó không làm việc cho tôi. Tôi chạy R trong Windows. Bất kỳ ý tưởng?
Ehsan88

4
Có cùng một lỗi, với một scriptt đã lưu và mới cài đặt và chạy R 3.2.0 trên windows ...
RalfB

27
Lỗi này xảy ra khi bạn cố gắng thực hiện dirname(sys.frame(1)$ofile)trực tiếp từ Rstudio. Nó hoạt động tốt khi tập lệnh được thực thi bằng nguồn ("other.R") và dirname(sys.frame(1)$ofile)nằm bên trong "other.R".
Murta

4
Tôi đã gặp lỗi 'không có nhiều khung trên ngăn xếp' khi gọi dưới dạng tập lệnh với rscript.exe tức là không sử dụng nguồn (). vì vậy tôi phải sử dụng giải pháp từ Suppressingfire bên dưới
Mark Adamson

3
Tôi gel NULLkhi cái này được đặt trong máy chủ.R khi sử dụng sáng bóng
Paul

75

Bạn có thể sử dụng commandArgschức năng để có được tất cả các tùy chọn đã được chuyển qua Rupcript cho trình thông dịch R thực tế và tìm kiếm chúng --file=. Nếu tập lệnh của bạn được khởi chạy từ đường dẫn hoặc nếu nó được khởi chạy với một đường dẫn đầy đủ, script.namebên dưới sẽ bắt đầu bằng một '/'. Mặt khác, nó phải liên quan đếncwd và bạn có thể nối hai đường dẫn để có được đường dẫn đầy đủ.

Chỉnh sửa: có vẻ như bạn chỉ cần phần script.nametrên và loại bỏ thành phần cuối cùng của đường dẫn. Tôi đã xóa cwd()mẫu không cần thiết và dọn sạch tập lệnh chính và đăng của tôi other.R. Chỉ cần lưu tập lệnh này và other.Rtập lệnh vào cùng thư mục chmod +x, và chạy tập lệnh chính.

chính.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)

khác.R :

print("hello")

đầu ra :

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"

Đây là những gì tôi tin rằng dehmann đang tìm kiếm.


Những gì với downmod?
Ức chế lửa

2
Tôi thất vọng vì kỹ thuật của bạn không hoạt động sourcenhư tôi nghĩ OP muốn - nhưng có lẽ tôi đã hiểu sai yêu cầu của anh ấy / cô ấy. Nhưng tôi không thể hủy bỏ :( Xin lỗi!
hadley

Nhưng thực sự, nó hoạt động tốt với nguồn! Chỉ cần nguồn (other.name) và nó hoạt động đúng.
Ức chế lửa

3
Để nối đường dẫn, tốt hơn nên sử dụngother.name <- file.path(script.basename, "other.R")
Jason

1
Khi tôi cố chạy commandArgs(trailingOnly = FALSE)bên trong máy chủ.R trong một ứng dụng sáng bóng, tôi nhận được [1] "RStudio" "--interactive". Không có thông tin về thư mục nó được gọi từ.
Paul

57

Tôi không thể làm cho giải pháp của Suppressingfire hoạt động khi 'nguồn' từ bảng điều khiển R.
Tôi không thể có được giải pháp của hadley để làm việc khi sử dụng Rupcript.

Tốt nhất của cả hai thế giới?

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))
        }
}

6
Tôi thích điều này bởi vì nó hoạt động với cả hai Rscriptsource()trong R. Tôi khuyên bạn nên thực hiện normalizePath()trên cả hai phiên bản, để nó đưa ra đường dẫn đầy đủ trong cả hai trường hợp.
wch

1
Đây là điều duy nhất đã làm việc. Lưu ý, để làm việc này, library(base)tôi phải mất một thời gian để tìm ra lol
O.rka

2
thưa ngài, hãy lấy phiếu bầu của tôi, bởi vì đây là giải pháp hiệu quả với tôi
Vince W.

1
Nếu điều này giúp bất cứ ai, cho bài viết gốc, điều đó có nghĩa là source(file.path(dirname(thisFile()), "other.R"))trong foo.R. Điều này làm việc cho tôi.
Kim

Một vấn đề. Giả sử trong nguồn RStudio I main.Rmà nguồn helper.Rnào gọi thisFile(). Nó sẽ lấy đường dẫn main.Rthay vì helper.R. Có lời khuyên nào ở đây không?
Wassadamo

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

Đừng hỏi tôi làm thế nào nó hoạt động, bởi vì tôi đã quên: /


2
Trong bối cảnh nào mà làm việc? print (sys.frames ()) bật NULL khi tôi chạy nó.
Ức chế

1
@Suppressingfire: sys.framestrả về các môi trường của ngăn xếp cuộc gọi, vì vậy nó chỉ thực sự có ý nghĩa khi được gọi từ một hàm. Hãy thử, ví dụ , foo <- function() {bar <- function() print(sys.frames()); bar()}; foo(). Tôi không thể tìm ra mã của @ hadley vì các môi trường không có ofilethành viên.
Cotton Richie

1
Bạn phải lấy tệp trong - tức là nếu tôi lưu mã đó thì chạy source("~/code/test.r"), PATHsẽ được đặt thành ~/desktop. Nếu bạn chỉ đánh giá nó ở cấp cao nhất, nó sẽ trả về NULL.
hadley

4
Điều này không trả lời câu hỏi của tôi. Tôi cần tự động tìm tệp "other.R". x$ofilelà không xác định, vì vậy frame_fileslà trống rỗng.
Frank

@hadley, mã rất hữu ích. Tôi đã có thể khái quát hóa chức năng tiện ích "tải lại tập lệnh hiện tại" mà tôi thêm vào gần như tất cả các tập lệnh khi chúng đang được phát triển. Trình tải lại RScript
Sim

29

Điều này làm việc cho tôi

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

4
Điều này chỉ hoạt động từ bên trong RStudio tôi đoán. Tôi đang cố gắng từ thiết bị đầu cuối Error: RStudio not running.
Ista

cụ thể hơn là nó hoạt động, nếu chạy từ tập lệnh R trong studio R. Ngay cả trên bảng điều khiển trong RStudio, nó sẽ không cho kết quả đúng ""trong trường hợp của tôi
Kay

Điều này hoạt động trong khi chạy tương tác trong Rstudio miễn là bạn không thay đổi tài liệu tập trung . Nếu bạn gửi các dòng để chạy và sau đó chuyển sang tài liệu khác trong khi chúng chạy, đường dẫn đến tài liệu khác sẽ được trả về.
Patrick

26

Câu trả lời của rakensi từ Lấy đường dẫn của tập lệnh R là IMHO chính xác và thực sự xuất sắc nhất. Tuy nhiên, nó vẫn là một hack kết hợp chức năng giả. Tôi đang trích dẫn nó ở đây, để người khác tìm thấy nó dễ dàng hơn.

sourceDir <- getSrcDirectory (hàm (giả) {dummy})

Điều này đưa ra thư mục của tệp nơi đặt câu lệnh (trong đó hàm giả được xác định). Sau đó, nó có thể được sử dụng để thiết lập thư mục làm việc và sử dụng các đường dẫn tương đối, vd

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

hoặc để tạo đường dẫn tuyệt đối

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

1
Đối với tôi, giải pháp của bạn là tốt nhất. Đặc biệt bởi vì nó có thể được áp dụng cho ứng dụng Shiny và ứng dụng trên liên kết thì không.
jcarlos

1
Ở đây getSrcDirectory là utils :: getSrcDirectory
RubenLaguna

5
Điều này có thể hoạt động tốt trong Linux / Mac, nhưng nó không hoạt động với tôi trong phiên RStudio tương tác trong Windows. sourceDirđã trống
Contango

1
@Contango trên một thiết bị đầu cuối tương tác, không có đường dẫn !!! Bạn muốn đường dẫn đến một tập tin.
pommedeterresautee

1
Tôi đang nhận được character(0). Gợi ý?
abalter

16

Tất cả của tôi trong một! (--01 / 09/2019 được cập nhật để đối phó với Bảng điều khiển RStudio)

#' 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)
                }
            }
        }
    }
}

Không hoạt động với phiên R tương tác; Tôi đang nhận được: `` `> source (" csf.R ")> csf () Lỗi: RStudio không
chạy`

Điều đó thật tuyệt. Ai đó có thể làm một gói?
Joe Flack

Điều này hoạt động trong khi chạy tương tác trong Rstudio miễn là bạn không thay đổi tài liệu tập trung. Nếu bạn gửi các dòng để chạy và sau đó chuyển sang tài liệu khác trong khi chúng chạy, đường dẫn đến tài liệu khác sẽ được trả về.
Patrick

13

Một biến thể rút gọn của câu trả lời của Supressingfire:

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

Điều này đã không làm việc đệ quy; tệp tôi tìm kiếm một tệp dữ liệu (nhưng trong thư mục sai).
Mèo Unun

11

Điều này làm việc cho tôi. Chỉ cần đưa nó ra khỏi các đối số dòng lệnh, loại bỏ văn bản không mong muốn, thực hiện một dirname và cuối cùng nhận được đường dẫn đầy đủ từ đó:

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

8

Tôi đã kết thúc và mở rộng các câu trả lời cho câu hỏi này thành một chức năng mới thisfile()trong rprojroot . Cũng hoạt động để đan với knitr.


6

Tôi thích giải pháp của steamer25 vì nó có vẻ mạnh mẽ nhất cho mục đích của tôi. Tuy nhiên, khi gỡ lỗi trong RStudio (trong windows), đường dẫn sẽ không được đặt đúng. Lý do là nếu một điểm dừng được đặt trong RStudio, việc tìm nguồn cung cấp tệp sử dụng lệnh "gỡ lỗi nguồn" thay thế để đặt đường dẫn kịch bản hơi khác một chút. Đây là phiên bản cuối cùng mà tôi hiện đang sử dụng tài khoản cho hành vi thay thế này trong RStudio khi gỡ lỗi:

# @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))
        }
    }
}

nguồn trong Rstudio đã cung cấp cho tôi, nhưng debugSource đã cho fileName để giải pháp của bạn hoạt động tốt nhưng các nhận xét về mã không hoàn toàn đúng trong trường hợp của tôi
Mark Adamson

6

Tôi đã thử hầu hết mọi thứ từ câu hỏi này, Nhận đường dẫn của tập lệnh R , Nhận đường dẫn của tập lệnh hiện tại , Tìm vị trí của tệp .R hiện tạilệnh R để đặt thư mục làm việc vào vị trí tệp nguồn trong Rstudio , nhưng cuối cùng, tôi thấy mình thủ công duyệt bảng CRAN và tìm thấy

scriptName thư viện

cung cấp current_filename()chức năng, trả về đường dẫn đầy đủ của tập lệnh khi tìm nguồn trong RStudio và cả khi gọi qua R hoặc RScript thực thi.


2
Package ‘scriptName’ was removed from the CRAN repository.- gì bây giờ? : o
Bojan P.

3

Tôi cũng có vấn đề này, và không có giải pháp nào ở trên làm việc cho tôi. Có lẽ vớisource thứ tương tự, nhưng nó không đủ rõ ràng.

Tôi tìm thấy điều này, đối với tôi thanh lịch, giải pháp:

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

Điều quan trọng trong đó là fileSnapshot()cung cấp cho bạn rất nhiều thông tin về một tập tin. Nó trả về một danh sách 8 yếu tố. Khi bạn chọn pathlàm thành phần danh sách, đường dẫn được trả về\\ dấu phân cách, vì vậy phần còn lại của mã chỉ là để thay đổi điều đó.

Tôi hi vọng cái này giúp được.


1
Điều này không làm việc cho tôi trên máy Linux; thay vì trả về đường dẫn của tệp, nó trả về thư mục mà tôi hiện đang nằm. Tôi đã tạo một tập lệnh thử nghiệm có tên TEST.R với một dòng mã: print (fileSnapshot () $ path) Tôi đã lưu nó trong thư mục này: / opt / home / boops / Desktop / Testfolder / TEST.RI sau đó điều hướng đến máy tính để bàn của tôi và cố gắng chạy tệp: boops @ linuxserver: ~ / Desktop $ Rscript /opt/home/boops/Desktop/Testfolder/TEST.R [1 ] "/ opt / home / boops / Desktop"
Boops Boops

Tôi cũng không làm việc. Trả về điều tương tự như 'here ()' khi sử dụng thư viện 'here'. Nó trả về đường dẫn đến dự án R hiện đang mở của tôi, nhưng bản thân anh ta không thực hiện.
Joe Flack

2

Bạn có thể gói tập lệnh r trong tập lệnh bash và truy xuất đường dẫn của tập lệnh dưới dạng biến bash như vậy:

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

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

     EOF

3
Điều này đòi hỏi bạn phải có đường dẫn kịch bản. Nó không cho phép bạn tạo một tập lệnh R thực sự di động có thể chạy từ bất cứ đâu.
Etienne Low-Décarie

@ EtienneLow-Décarie Nó không yêu cầu đường dẫn kịch bản, nó lấy nó từ bash. Vấn đề chính là nó không phải là một cách đáng tin cậy để có được con đường. Một cái gì đó như thế này được ưu tiên, như trong stackoverflow.com/questions/59895/ trên đường dẫn_to_script = "$ (cd" $ (dirname "$ {BASH_SOURCE [0]}") "&& pwd)"
John Haberstroh

2

Tôi thích cách tiếp cận này:

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

2

Tôi chỉ làm việc này ra bản thân mình. Để đảm bảo tính di động của tập lệnh của bạn, hãy luôn bắt đầu bằng:

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

Nó hoạt động vì "." dịch như lệnh Unix $ PWD. Việc gán chuỗi này cho một đối tượng ký tự cho phép bạn chèn đối tượng ký tự đó vào setwd () và Presto mã của bạn sẽ luôn chạy với thư mục hiện tại của nó là thư mục làm việc, bất kể nó nằm ở đâu hoặc ở đâu trong cấu trúc tệp nằm. (Phần thưởng thêm: Đối tượng wd có thể được sử dụng với file.path () (tức là file.path (wd, "output_directory") để cho phép tạo thư mục đầu ra tiêu chuẩn bất kể đường dẫn tệp dẫn đến thư mục được đặt tên của bạn. Điều này không yêu cầu bạn tạo thư mục mới trước khi tham chiếu theo cách này, nhưng điều đó cũng có thể được hỗ trợ với đối tượng wd.

Cách khác, đoạn mã sau thực hiện chính xác điều tương tự:

wd <- getwd()
setwd(wd)

hoặc, nếu bạn không cần đường dẫn tệp trong một đối tượng, bạn có thể chỉ cần:

setwd(".")

11
Không. Điều đó tìm thấy thư mục của quá trình, không phải chính tập tin.
dùng1071847

Điều này làm việc cho tôi trong Windows với RStudio ở chế độ tương tác.
Contango

2

Lưu ý rằng gói getopt cung cấp get_Rscript_filenamechức năng, chỉ sử dụng cùng một giải pháp được trình bày ở đây, nhưng đã được viết cho bạn trong mô-đun R tiêu chuẩn, do đó bạn không phải sao chép và dán chức năng "lấy đường dẫn tập lệnh" vào mọi tập lệnh bạn viết.


Nó luôn trả về NA, ngay cả khi tôi tạo tập lệnh in kết quả đầu ra và sau đó gọi tập lệnh, ví dụ: vớiR -e "library(getopt); testscript.R"
bokov

1
Như tên của hàm ngụ ý, bạn cần chạy tập lệnh của mình bằng cách sử dụng Rscript.
Ryan C. Thompson

À, ôi. Cảm ơn.
bokov

1

Xem findSourceTraceback()các R.utils gói, trong đó

Tìm tất cả các đối tượng 'srcfile' được tạo bởi source () trong tất cả các khung gọi. Điều này cho phép tìm ra các tập tin hiện đang được viết mã theo nguồn ().


1

Tôi gặp vấn đề với việc triển khai ở trên vì tập lệnh của tôi được vận hành từ thư mục được liên kết hoặc ít nhất đó là lý do tại sao tôi nghĩ các giải pháp trên không hiệu quả với tôi. Dọc theo dòng câu trả lời của @ ennuikiller's, tôi đã gói bản thảo của mình vào bash. Tôi đặt biến đường dẫn bằng cách sử dụng pwd -P, nó giải quyết các cấu trúc thư mục được liên kết. Sau đó vượt qua đường dẫn vào Rupcript.

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)

1

Tôi sẽ sử dụng một biến thể của phương pháp @ steamer25. Vấn đề là tôi thích có được tập lệnh có nguồn gốc cuối cùng ngay cả khi phiên của tôi được bắt đầu thông qua Rupcript. Đoạn mã sau, khi được đưa vào một tệp, sẽ cung cấp một biến thisScriptchứa đường dẫn chuẩn hóa của tập lệnh. Tôi thú nhận việc sử dụng nguồn (ab), do đó, đôi khi tôi gọi ra Rupcript và tập lệnh được cung cấp trong --fileđối số sẽ tạo một tập lệnh khác lấy một tập lệnh khác ... Một ngày nào đó tôi sẽ đầu tư vào việc biến mã lộn xộn của mình thành một gói.

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))
  }
})()

1

99% các trường hợp bạn có thể chỉ cần sử dụng:

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

Nó sẽ không hoạt động đối với các cuộc gọi điên rồ khi kịch bản không phải là đối số đầu tiên, nghĩa là , source(some args, file="myscript"). Sử dụng @ hadley's trong những trường hợp ưa thích này.


Tuy nhiên, không phải từ bên trong RStudio, ngoại trừ khi tìm nguồn cung ứng
nJGL

1

Cách tiếp cận của Steamer25 hoạt động, nhưng chỉ khi không có khoảng trắng trong đường dẫn. Trên macOS ít nhất là cmdArgs[match]trả về một cái gì đó như /base/some~+~dir~+~with~+~whitespace/cho /base/some\ dir\ with\ whitespace/.

Tôi đã giải quyết vấn đề này bằng cách thay thế "~ + ~" bằng một khoảng trắng đơn giản trước khi trả lại.

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))
  }
}

Rõ ràng bạn vẫn có thể mở rộng khối khác như aprstar đã làm.


1

Nếu thay vì tập lệnh, foo.Rbiết vị trí đường dẫn của nó, nếu bạn có thể thay đổi mã của mình để luôn tham chiếu tất cả các sourceđường dẫn từ chung rootthì đây có thể là một trợ giúp tuyệt vời:

Được

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

Điều này sẽ làm việc

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

Xem https://rprojroot.r-lib.org/ để biết cách xác định gốc dự án.


Đối với tôi gói ở đây thực hiện chính xác công việc và dường như là một giải pháp dễ dàng
Ron

0
#!/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='/'))

Tôi vẫn gặp lỗi "Lỗi trong sys.frame (1): không có nhiều khung trên ngăn xếp"
Michael Barton

0

Thật ngạc nhiên khi không có cấu trúc kiểu '$ 0' trong R! Bạn có thể thực hiện với lệnh gọi system () tới tập lệnh bash được viết bằng R:

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

Sau đó, chỉ cần tách tên scriptpath.sh cho khác.R

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

Tôi nhận được một thông báo lỗireadLink: illegal option -- e usage: readLink [-FlLnqrsx] [-f format] [-t timefmt] [file ...]
altabq

0

Bằng cách nhìn vào ngăn xếp cuộc gọi, chúng ta có thể nhận được filepath của mỗi tập lệnh đang được thực thi, hai tập lệnh hữu ích nhất có thể là tập lệnh hiện đang thực thi hoặc tập lệnh đầu tiên có nguồn gốc (mục nhập).

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) ))()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.