Определить путь к исполняемому скрипту - PullRequest
220 голосов
/ 29 ноября 2009

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

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

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

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

Ответы [ 24 ]

6 голосов
/ 14 августа 2015

Мне понравилось решение 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))
        }
    }
}
6 голосов
/ 13 ноября 2018

Я попробовал почти все из этого вопроса, Получение пути R-скрипта , Получение пути текущего скрипта , Найти местоположение текущего .R файла и R команда для установки рабочего каталога в качестве местоположения исходного файла в Rstudio , но в конце концов оказалась сама вручную просматривая таблицу CRAN и находя

scriptName библиотека

, которая предоставляет функцию current_filename(), которая возвращает правильный полный путь скрипта при поиске в RStudio, а также при вызове через исполняемый файл R или RScript.

5 голосов
/ 05 августа 2016

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

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

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

Альтернативно, следующий код выполняет ту же функцию:

wd <- getwd()
setwd(wd)

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

setwd(".")
2 голосов
/ 29 ноября 2009

Вы можете обернуть скрипт 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
2 голосов
/ 16 марта 2017

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

2 голосов
/ 17 декабря 2014

Мне нравится такой подход:

this.file <- sys.frame(tail(grep('source',sys.calls()),n=1))$ofile
this.dir <- dirname(this.file)
1 голос
/ 18 мая 2014

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

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

1 голос
/ 25 ноября 2016

99% случаев, которые вы можете просто использовать:

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

Он не будет работать для сумасшедших вызовов, когда сценарий не является первым аргументом, то есть source(some args, file="myscript"). Используйте @ hadley's в этих необычных случаях.

1 голос
/ 02 сентября 2015

Я бы использовал вариант подхода @ 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))
  }
})()
1 голос
/ 27 мая 2015

У меня были проблемы с реализациями, описанными выше, поскольку мой скрипт работает из каталога с символическими ссылками, или, по крайней мере, поэтому я думаю, что вышеупомянутые решения не сработали для меня. В соответствии с ответом @ 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)
...