2012-01-12 4 views
18

Как файл source d или Sweave d найти свой собственный путь?получить имя файла и путь к файлу `source`d

фона:

Я много работаю с .r сценариев или .Rnw файлов. Мои проекты организованы в структуре каталогов, но путь к базовому каталогу проекта часто варьируется между разными компьютерами (например, потому что я просто делаю части анализа данных для кого-то другого, а их структура каталогов отличается от моей: у меня есть база проектов каталоги ~/Projects/StudentName/или ~/Projects/Studentname/Projectname и большинство студентов, у которых есть только один проект, обычно имеют его под ~/Measurements/or ~/DataAnalysis/или что-то подобное - что не будет работать для меня) ,

Так линия, как

setwd (my.own.path()) 

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

Позвольте пояснить: Я ищу решение, которое работает с нажатием клавиши редактора/IDE source или Sweave Клавиатурный ярлык для бездумного пользователя.

+2

Опция 'chdir'' source' похоже на то, что вы просите. – James

+1

Моя типичная компоновка для этого - разместить каталог проектов каждого компьютера в символьной переменной, заданной в .Rprofile. –

+0

@James: Это частичное решение. Если мне нужно ввести 'source (" project/path/file.R ", chdir = TRUE)' Мне не лучше, чем набирать 'setwd (" project/path ") и ударить ярлык для взаимодействия (большинство пользователей начнется со сценария, возможно, «source», а затем продолжится более или менее интерактивно, когда вы настраиваете/добавляете скрипт или файл Sweave. – cbeleites

ответ

10

Просто FYI, knitr будет setwd() к директории входного файла, когда (и только когда) оценивания кусков кода, то есть, если вы звоните knit('path/to/input.Rnw'), рабочий реж будет временно переключился на path/to/. Если вы хотите знать входной каталог в фрагментах кода, в настоящее время вы можете вызывать неэкспонированную функцию knitr:::input_dir() (я могу экспортировать ее в будущем).

+0

Уважаемый Yihui, я должен знать - я не знал о 'knitr', и он выглядит очень многообещающим. – cbeleites

+0

Замечательно, что у knitr есть это умное поведение по умолчанию. Однако 'knitr ::: input_dir()' defaults to "." даже когда в Rstudio выполняется кусок knitr. Мой рабочий процесс создает скрипт в Rstudio и только вязание в конце - поэтому 'knitr ::: input_dir()' недостаточно. – Ruben

+0

@Ruben Я думаю, что это недоразумение из-за того, что вы использовали RStudio: RStudio делает 'setwd()' (устанавливает рабочий каталог в каталог вашего входного файла) перед вызовом 'knitr', и именно поэтому вы видите '.', что абсолютно правильно. Вы должны проверить его вне RStudio, например. запускаться в библиотеке R-терминалов (knitr); knit ('path/to/input.Rnw') ', тогда вы увидите' input_dir() 'is' path/to/' –

3

У меня нет прямого решения, как получить каталог самого файла, но если у вас есть ограниченный набор каталогов и структуры каталогов вы можете, вероятно, использовать

if(file.exists("c:/somedir")==TRUE){setwd("c:/somedir")} 

Вы можете проверить шаблон каталога в вопросе, а затем установить каталог. Это вам помогает?

+0

Seb, к сожалению, имена в каталогах разных лиц предпочитают, по-видимому, совсем иначе ... – cbeleites

+0

Можно было разыскать все дерево каталогов один раз, а затем записать результирующий каталог в константа хранится в .Rprofile? :-) –

+0

Время, необходимое для поиска всего дерева каталогов, должно научить кого-либо организовывать себя с помощью каталога Projects ;-) – cbeleites

11

С предложениями Себ в GSK3, вот идея:

  • сочетание имени пользователя (логин) и IP или имя компьютера может быть использован, чтобы выбрать правильный каталог.

Это приводит к чему-то вроде:

setwd (switch (paste (Sys.info() [c ("user", "nodename")], collapse="."), 
      user.laptop = "~/Messungen", 
      user2.server = "~/Projekte/Projekt/", 
      )) 

Так происходит автоматическое решение, которое

  • работы с source
  • работы с Sweave
  • работает даже для интерактивного сеансы, где команды отправляются по строкам

  • сочетание user и nodename конечно должно быть конкретным

  • пути должны быть отредактированы вручную, хотя.

Усовершенствования приветствуются!


Update:

Габор Гротендик ответил следующее на соответствующий вопрос о г-помощи сегодня:

this.dir <- dirname(parent.frame(2)$ofile) 
setwd(this.dir) 

, который будет работать для source.


Другое обновление: теперь я выполняю большую часть работы по анализу данных в RStudio. Проекты RStudio в основном решают проблему: RStudio меняет рабочий каталог на корневой каталог проекта каждый раз, когда я переключаюсь между проектами.

Поэтому я могу разместить каталог проекта так далеко от моего дерева каталогов, как я хочу (и студенты могут также поместить свою копию туда, где они хотят), и синхронизировать файлы данных и скрипты/.Rnw с помощью контроля версий (мы используем частный git-сервер). Файлы проекта RStudio хранятся вне контроля версии, то есть .gitignore содержит .Rproj.user.

Очевидно, в пределах проекта, структура каталогов должна быть синхронизирована.

+0

На данный момент я придерживаюсь этого, так как он позволяет пользователям легко (то есть без зависимости от функции 'setwd' их редактора) использовать файлы в интерактивном режиме во время их разработки. Спасибо за вклад, который позволил мне получить эту идею. – cbeleites

+1

Первое решение не работает в произвольной среде, решение Grothendieck не работает на моем mac (parent.frame() не имеет $ $). – Ruben

+0

@cbeleites В Rstudio на компьютере с Windows это сообщение об ошибке «Ошибка в dirname (parent.frame (2) $ oile): ожидаемый аргумент символьного вектора« – MHH

4

Вы можете использовать sys.calls(), чтобы получить команду, используемую для источника файла. Затем вам нужно немного обмана, используя регулярные выражения, чтобы получить путь, учитывая, что source("something/filename") мог использовать либо абсолютный, либо относительный путь. Вот первая попытка собрать все части: попробуйте вставить следующие строки в верхней части исходного файла.

whereFrom=sys.calls()[[1]] 
# This should be an expression that looks something like 
# source("pathname/myfilename.R") 
whereFrom=as.character(whereFrom[2]) # get the pathname/filename 
whereFrom=paste(getwd(),whereFrom,sep="/") # prefix it with the current working directory 
pathnameIndex=gregexpr(".*/",whereFrom) # we want the string up to the final '/' 
pathnameLength=attr(pathnameIndex[[1]],"match.length") 
whereFrom=substr(whereFrom,1,pathnameLength-1) 
print(whereFrom) # or "setwd(whereFrom)" to set the working directory 

Это не очень надежный —, например, она не будет выполнена на окнах с source("pathname\\filename"), и я не проверял, что происходит, если у вас есть один файл Sourcing другой файл — но вы можете быть в состоянии построить решение на наверху этого.

2

Дополнительная проблема заключается в том, что рабочий каталог является глобальной переменной, которая может быть изменена любым скриптом, поэтому, если ваш сценарий вызывает другой скрипт, ему придется установить wd обратно. В RStudio я использую Session -> Set Working Directory -> Для Source File Откуда (я знаю, это не идеал), а затем мой сценарий делает

wd = getwd() 
... 
source ("mySubDir/myOtherScript.R", chdir=TRUE); setwd (wd) 
... 
source ("anotherSubDir/anotherScript.R", chdir=TRUE); setwd (wd) 

Таким образом, можно поддерживать стек рабочих каталогов. Я хотел бы, чтобы это было реализовано на самом языке.

0

Этот ответ работает для source, а также внутри nvim-R - Я понятия не имею, работает ли он с knitr и аналогичными вещами. Любые отзывы оцениваются.

Если у вас есть несколько сценариев source -приняв друг друга, важно получить правильный. То есть наибольший i, для которого существует sys.frame(i)$ofile.

get.full.path.to.this.sourced.script = function() {  
    for(i in sys.nframe():1) { # Go through all the call frames, 
           # in *reverse* order. 
     x = sys.frame(i)$ofile 
     if(!is.null(x))    # if $ofile exists, 
      return(normalizePath(x)) # then return the full absolute path 
    } 
} 
Смежные вопросы