Как узнать путь к файлу R внутри него, когда он получен? - PullRequest
0 голосов
/ 13 апреля 2020

Когда я отправляю файл в R, я хочу знать внутри него, каков его путь. Есть ли способ сделать это в R?

source("somefile.R")

См. BASH_SOURCE (хотя мне просто нужно ${BASH_SOURCE[0]}) для аналогичной функции в bash.

https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html

РЕДАКТИРОВАТЬ: Следующее решение не работает, как ожидалось. См. f(), вызываемый снаружи main1.R.

$ cat main1.R 

f = function() {
if (!is.null(src <- Sys.getenv("R_SOURCE")) && nzchar(src)) {
    cat("my name is '", src, "'\n", sep = "")
}
}

f() 
$ Rscript main.R 
R> source2 <- function(path, ...) {
+   path <- normalizePath(path)
+   oldsrc <- Sys.getenv("R_SOURCE")
+   on.exit({ Sys.setenv(R_SOURCE = oldsrc) }, add = TRUE)
+   Sys.setenv(R_SOURCE = path)
+   source(path, ...)
+ }
R> 
R> source2('main1.R')
my name is '/private/tmp/y/main1.R'
R> f()
R> 

В bash, независимо от того, где вызывается функция, она всегда знает, где она определена.

$ cat ./main1.sh 
#!/usr/bin/env bash
# vim: set noexpandtab tabstop=2:

function f {
  declare -p BASH_SOURCE
}
$ cat ./main.sh 
#!/usr/bin/env bash
# vim: set noexpandtab tabstop=2:

source main1.sh
set -v
declare -p BASH_SOURCE
f

$ ./main.sh 
declare -p BASH_SOURCE
declare -a BASH_SOURCE=([0]="./main.sh")
f
declare -a BASH_SOURCE=([0]="main1.sh" [1]="./main.sh")

РЕДАКТИРОВАТЬ:

Следующее решение на основе getSrcFilename() не работает, когда кто-то хочет получить доступ к пути в файле, запускаемом Rscript.

$ cat f.R 
f=function() {
  getSrcFilename(f)
}

(function() {
  print(getSrcFilename(f))
})()
$ Rscript f.R
R> f=function() {
+   getSrcFilename(f)
+ }
R> 
R> (function() {
+   print(getSrcFilename(f))
+ })()
character(0)
R> 

Ответы [ 2 ]

1 голос
/ 15 апреля 2020

Если вы считаете, что данное решение не работает, то, вероятно, вы не просто хотите знать путь при создании файла, но постоянно для любых объектов, которые он создает.

srcref система предоставляет хотя бы часть того, что вы хотите, если options(keep.source=TRUE)

Например:

> source("~/Downloads/main.R")
> getSrcFilename(svy_vglm,full.names=TRUE)
[1] "svgam.R"
> getSrcFilename(f)
[1] "main.R"
> getSrcDirectory(f)
[1] "/Users/tlum005/Downloads"

Каталог - это каталог, по которому был найден файл: если вы только что сделали source("main.R") каталог будет ., а не его абсолютная форма.

Переписав свой main.R, вы можете получить

f = function() {

   cat(getSrcDirectory(f))

}

f()

Здесь есть две слабые стороны: атрибуты srcref копируются по присваиванию, а f() полагается на знание своего собственного имени. Если вы сделали

g<-f
g()
rm(f)
g()

, вы можете захотеть, чтобы два вызова g() вернули оба ошибки (так как g() не было получено) или оба возвращали каталог, но вы не захотите каждого. В этом случае это можно обойти с помощью sys.function(): если main.R равно

f = function() {

   cat(getSrcDirectory(sys.function()))

}

f()

назначение работает

> source("~/Downloads/main.R")
/Users/tlum005/Downloads
> f()
/Users/tlum005/Downloads
> g<-f
> g()
/Users/tlum005/Downloads
> rm(f)
> g()
/Users/tlum005/Downloads

Я бы не стал пропагандировать с использованием этот метод - я не могу придумать ситуацию, когда вам было бы не лучше просто разместить исходный код где-то лучше организованным - но я думаю, что он действительно отвечает на вопрос.

0 голосов
/ 14 апреля 2020

Возможно, вы могли бы использовать path_abs() из пакета fs?

https://fs.r-lib.org/reference/path_math.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...