Получить путь от текущего script

Я хотел бы установить рабочий каталог на путь текущего script программно, но сначала мне нужно получить путь к текущему script.

Итак, я хотел бы иметь возможность сделать:

current_path = ...retrieve the path of current script ...
setwd(current_path) 

Так же, как в меню RStudio: RStudio установить рабочий каталог

До сих пор я пытался:

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)

script.name возвращает NULL

source("script.R", chdir = TRUE)

Возвращает: Ошибка в файле (имя файла, "r", кодирование = кодировка): не удается открыть соединение Дополнительно: Предупреждающее сообщение: В файле (имя файла, "r", encoding = encoding): невозможно открыть файл '/ script.R': нет такого файла или Каталог

dirname(parent.frame(2)$ofile)

Возвращает: ошибка в dirname (parent.frame(2) $ofile): ожидаемый аргумент символьного символа... потому что parent.frame имеет значение null

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

Возвращает: Нуль, потому что frame_files - это список 0

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

Возвращает: ошибка в пути .expand(путь): недопустимый аргумент "путь"

Также я увидел все ответы здесь, здесь, здесь и здесь. Нет радости.

Работа с RStudio 1.1.383

EDIT: Было бы здорово, если бы не понадобилась внешняя библиотека для этого.

Ответ 1

В RStudio вы можете получить путь к файлу, отображаемому в настоящее время в исходной панели, используя

rstudioapi::getSourceEditorContext()$path

Если вам нужен только каталог, используйте

dirname(rstudioapi::getSourceEditorContext()$path)

Если вам нужно имя файла, который был запущен source(filename), это немного сложнее. Вам нужно искать переменную srcfile где-то в стеке. Как далеко назад зависит то, как вы пишете вещи, но это примерно на 4 шага назад: например,

fi <- tempfile()
writeLines("f()", fi)
f <- function() print(sys.frame(-4)$srcfile)
source(fi)
fi

должен печатать то же самое на двух последних строках.

Ответ 2

Обновление августа 2018

TL;DR: пакет here помогает вам создать путь из корневой папки проекта, независимо от того, где в папке hiearchy хранятся скрипты R или документы Rmd.

Здесь пакет остается доступным на CRAN. Версия для разработки была перемещена на github.com/r-lib/here. Пункты, упомянутые на сайтах, указанных ниже, остаются в силе.

Предыдущий ответ

Прочтите Оду здесь:

Есть ли у вас setwd() в ваших скриптах? Пожалуйста, прекратите делать это. Это делает ваш сценарий очень хрупким, запрограммированным точно в одно время и в одном месте. Как только вы переименовываете или перемещаете каталоги, он ломается. Или, может быть, вы получите новый компьютер? Или, может быть, кому-то еще нужно запустить ваш код?

[...]

Классическое представление проблемы: неловкость вокруг путей построения и/или установки рабочего каталога в проектах с подкаталогами. Особенно, если вы используете R Markdown и knitr, которые запутывают многих людей с помощью поведения по умолчанию "рабочий каталог = каталог, в котором находится этот файл". [...]

Установите здесь пакет:

install.packages("here")
library(here)
here()
here("construct","a","path")

Документирование функции here():

Начиная с текущего рабочего каталога во время загрузки пакета, здесь будет проходить иерархия каталогов вверх, пока не будет найден каталог, удовлетворяющий хотя бы одному из следующих условий:

  • содержит файл, соответствующий [.] Rproj $ с содержанием, совпадающим с ^ Версия: в первой строке
  • [... другие опции...]
  • содержит каталог .git

После установки корневой каталог не изменяется во время активного сеанса R. здесь() затем добавляет аргументы в корневой каталог.

Разрабатываемая версия пакета доступна на github.

Ответ 3

Если вы запускаете Rscript через командную строку и т.д.

Rscript /path/to/script.R

Функция ниже назначит this_file /path/to/script

library(tidyverse)
get_this_file <- function(){
    commandArgs() %>% 
       tibble::enframe(name=NULL) %>%
       tidyr::separate(col=value, into=c("key", "value"), sep="=", fill='right') %>%
       dplyr::filter(key == "--file") %>%
       dplyr::pull(value)
}
this_file <- get_this_file()

Ответ 4

Обновление март 2019

На основе ответов Alexis Lucattini и user2554330, чтобы он работал как в командной строке, так и в RStudio. Также решение устаревшего сообщения "as_tibble"

library(tidyverse)
getCurrentFileLocation <-  function()
{
    this_file <- commandArgs() %>% 
    tibble::enframe(name = NULL) %>%
    tidyr::separate(col=value, into=c("key", "value"), sep="=", fill='right') %>%
    dplyr::filter(key == "--file") %>%
    dplyr::pull(value)
    if (length(this_file)==0)
    {
      this_file <- rstudioapi::getSourceEditorContext()$path
    }
    return(dirname(this_file))
}

Ответ 5

Другой способ получить текущий путь к скрипту - это funr::get_script_path() и вам не нужно запускать ваш скрипт с помощью RStudio.

Ответ 6

У меня были проблемы со всем этим, потому что они полагаются на библиотеки, которые я не мог использовать (из-за packrat) до тех пор, пока не установил рабочий каталог (именно поэтому мне нужно было получить путь для начала).

Итак, вот подход, который просто использует базу R. (EDITED для обработки окон\символов в дополнение к/в путях)

args = commandArgs()

scriptName = args[substr(args,1,7) == '--file=']

if (length(scriptName) == 0) {
  scriptName <- rstudioapi::getSourceEditorContext()$path
} else {
  scriptName <- substr(scriptName, 8, nchar(scriptName))
}

pathName = substr(
  scriptName, 
  1, 
  nchar(scriptName) - nchar(strsplit(scriptName, '.*[/|\\]')[[1]][2])
)