Получить путь к текущему сценарию

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

Поэтому я хотел бы иметь возможность сделать:

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", кодировка = кодировка): не удается открыть файл '/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)]])

Возвращает: Null, потому что 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))
    }
}

Возвращает: Ошибка в path.expand (path): неверный аргумент 'path'

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

Работать с RStudio 1.1.383

РЕДАКТИРОВАТЬ: Было бы здорово, если бы не было необходимости во внешней библиотеке для достижения этой цели.

3 ответа

Решение

В 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

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

Обновление март 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))
}

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

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

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

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

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

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

[...]

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

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

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

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

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

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

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

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

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

Rscript /path/to/script.R

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

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

Вот настраиваемая функция для получения пути к файлу в R, RStudio или из Rscript:

stub <- function() {}
thisPath <- function() {
  cmdArgs <- commandArgs(trailingOnly = FALSE)
  if (length(grep("^-f$", cmdArgs)) > 0) {
    # R console option
    normalizePath(dirname(cmdArgs[grep("^-f", cmdArgs) + 1]))[1]
  } else if (length(grep("^--file=", cmdArgs)) > 0) {
    # Rscript/R console option
    scriptPath <- normalizePath(dirname(sub("^--file=", "", cmdArgs[grep("^--file=", cmdArgs)])))[1]
  } else if (Sys.getenv("RSTUDIO") == "1") {
    # RStudio
    dirname(rstudioapi::getSourceEditorContext()$path)
  } else if (is.null(attr(stub, "srcref")) == FALSE) {
    # 'source'd via R console
    dirname(normalizePath(attr(attr(stub, "srcref"), "srcfile")$filename))
  } else {
    stop("Cannot find file path")
  }
}

https://gist.github.com/jasonsychau/ff6bc78a33bf3fd1c6bd4fa78bbf42e7

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

Следующее решает проблему для трех случаев: кнопка источника RStudio, консоль RStudio R (source(...), если файл все еще находится на панели "Источник") или в консоли ОС через Rscript:

this_file = gsub("--file=", "", commandArgs()[grepl("--file", commandArgs())])
if (length(this_file) > 0){
  wd <- paste(head(strsplit(this_file, '[/|\\]')[[1]], -1), collapse = .Platform$file.sep)
}else{
  wd <- dirname(rstudioapi::getSourceEditorContext()$path)
}

print(wd)

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

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

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

Следующий код указывает каталог запущенного Rscript, если вы запускаете его из Rstudio или из командной строки с помощью команды Rscript:

if (rstudioapi::isAvailable()) {
  if (require('rstudioapi') != TRUE) {
    install.packages('rstudioapi')
  }else{
    library(rstudioapi) # load it
  }
 wdir <- dirname(getActiveDocumentContext()$path)
}else{
 wdir <- getwd()
}

setwd(wdir)

Если вы не хотите использовать (или должны помнить) код, просто наведите указатель мыши на сценарий, и появится путь

ht tps:https://stackru.com/images/e8e1204e4b59d1eaac2302bb49c47b89fc2a9d85.png

Другие вопросы по тегам