[file] Rscript: определение пути исполняемого скрипта



Answers

Вы можете использовать функцию commandArgs чтобы получить все параметры, которые были переданы Rscript, фактическому интерпретатору R и искать их для --file= . Если ваш скрипт был запущен с пути или был запущен с полным путем, имя script.name ниже начинается с script.name '/' . В противном случае это должно быть относительно cwd и вы можете выполнить два пути, чтобы получить полный путь.

Редактировать: похоже, вам понадобится только script.name выше и удалить последний компонент пути. Я удалил ненужный cwd() образец и очистил основной скрипт и опубликовал мой other.R . Просто сохраните этот скрипт и скрипт other.R в том же каталоге, chmod +x them и запустите основной скрипт.

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 <- paste(sep="/", 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"

Это то, что я считаю дехманом.

Question

У меня есть скрипт под названием foo.R который включает в себя другой скрипт other.R , который находится в том же каталоге:

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

Но я хочу, чтобы R обнаружил, что other.R независимо от того, что текущий рабочий каталог.

Другими словами, foo.R должен знать свой собственный путь. Как я могу это сделать?




Все в одном!

#' current script file (in full path)
#' @param
#' @return
#' @examples
#' works with Rscript, source() or in RStudio Run selection
#' @export
csf <- function() {
    # http://.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://.com/a/35842176/2292993  
                return(normalizePath(rstudioapi::getActiveDocumentContext()$path))
            }
        }
    }
}



Ответ rakensi от получения пути к R-скрипту является самым правильным и действительно блестящим IMHO. Тем не менее, это все еще хак, включающий фиктивную функцию. Я цитирую его здесь, чтобы облегчить его поиск другими.

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

Это дает каталог файла, в который был помещен оператор (где определена фиктивная функция). Затем он может использоваться для установки рабочей директории и использования относительных путей, например

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

или создать абсолютные пути

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



Я просто справился с этим сам. Чтобы обеспечить переносимость вашего скрипта, всегда начинайте с:

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

Это работает, потому что "." переводится как команда Unix $ PWD. Присвоение этой строки символьному объекту позволяет затем вставить этот объект символа в setwd (), а Presto ваш код будет всегда запускаться с его текущим каталогом в качестве рабочего каталога, независимо от того, на чьей машине он находится или где в файловой структуре это располагается. (Дополнительный бонус: wd-объект можно использовать с file.path () (то есть file.path (wd, «output_directory»), чтобы создать стандартный выходной каталог независимо от пути к файлу, ведущего к вашей именованной директории. Это требует от вас сделать новый каталог, прежде чем ссылаться на него таким образом, но этому тоже может помочь объект wd.

В качестве альтернативы, следующий код выполняет то же самое:

wd <- getwd()
setwd(wd)

или, если вам не нужен путь к файлу в объекте, вы можете просто:

setwd(".")



Обратите внимание, что пакет getopt предоставляет функцию get_Rscript_filename , которая просто использует то же самое решение, представленное здесь, но уже написано для вас в стандартном R-модуле, поэтому вам не нужно копировать и вставлять функцию «get script path» в каждый сценарий вы пишете.




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



Если вместо скрипта foo.R , зная его местоположение пути, если вы можете изменить свой код, чтобы всегда ссылаться на все source пути d из общего root то это может быть большой помощью:

Данный

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

Это будет работать

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

См. https://krlmlr.github.io/rprojroot/ о том, как определить корни проекта.




Я завершил и расширил ответы на этот вопрос в новую функцию thisfile() в моем пакете misc . Также работает для вязания с knitr .




См. findSourceTraceback() пакета R.utils , который

Находит все объекты srcfile, сгенерированные источником () во всех кадрах вызовов. Это позволяет узнать, какие файлы в настоящее время написаны с помощью source ().




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

Не спрашивайте меня, как это работает, потому что я забыл: /




Я бы использовал вариант подхода @ steamer25. Дело в том, что я предпочитаю получать последний скрипт, даже когда мой сеанс был запущен через Rscript. Следующий фрагмент, если он включен в файл, предоставит переменную thisScript содержащую нормализованный путь к скрипту. Я признаю (ab) использование source'ing, поэтому иногда я вызываю 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))
  }
})()



Links