Existe-t-il un moyen de rechercher par programmation le chemin d'un script R dans le script lui-même?
Je vous pose cette question car plusieurs scripts utilisent RGtk2
et chargent une interface graphique à partir d’un fichier .glade.
Dans ces scripts, je suis obligé de mettre une instruction setwd("path/to/the/script")
au début, sinon le fichier .glade (qui se trouve dans le même répertoire) ne sera pas trouvé.
C'est bien, mais si je déplace le script dans un autre répertoire ou sur un autre ordinateur, je dois changer le chemin. Je sais, ce n'est pas grave, mais ce serait bien d'avoir quelque chose comme:
setwd(getScriptPath())
Alors, une fonction similaire existe-t-elle?
Utilisez source("yourfile.R", chdir = T)
Cela fonctionne pour moi:
getSrcDirectory(function(x) {x})
Cela définit une fonction anonyme (qui ne fait rien) dans le script, puis détermine le répertoire source de cette fonction, qui est le répertoire dans lequel se trouve le script.
Pour RStudio uniquement:
setwd(dirname(rstudioapi::getActiveDocumentContext()$path))
Cela fonctionne quand Run ning ou Source ing votre fichier.
Exploiter l'argument implicite "--file" de Rscript
Lors de l'appel du script à l'aide de "Rscript" ( Rscript doc ), le chemin complet du script est indiqué en tant que paramètre système. La fonction suivante exploite cela pour extraire le répertoire du script:
getScriptPath <- function(){
cmd.args <- commandArgs()
m <- regexpr("(?<=^--file=).+", cmd.args, Perl=TRUE)
script.dir <- dirname(regmatches(cmd.args, m))
if(length(script.dir) == 0) stop("can't determine script dir: please call the script with Rscript")
if(length(script.dir) > 1) stop("can't determine script dir: more than one '--file' argument detected")
return(script.dir)
}
Si vous enveloppez votre code dans un package, vous pouvez toujours interroger des parties du répertoire du package.
Voici un exemple tiré du package RGtk2:
> system.file("ui", "demo.ui", package="RGtk2")
[1] "C:/opt/R/library/RGtk2/ui/demo.ui"
>
Vous pouvez faire la même chose avec un répertoire inst/glade/
dans vos sources qui deviendra un répertoire glade/
dans le paquet installé - et system.file()
calculera le chemin pour vous lors de l'installation, quel que soit le système d'exploitation.
Cette réponse me convient parfaitement:
script.dir <- dirname(sys.frame(1)$ofile)
Remarque: le script doit être recherché pour renvoyer le chemin correct.
Je l'ai trouvé dans: https://support.rstudio.com/hc/communities/public/questions/200895567-can-user-obtain-the-path-of-current-Project-s-directory-
Mais je ne comprends toujours pas ce qu'est sys.frame (1) $ ofile. Je n'ai rien trouvé à ce sujet dans R Documentation. Quelqu'un peut l'expliquer?
#' current script dir
#' @param
#' @return
#' @examples
#' works with source() or in RStudio Run selection
#' @export
z.csd <- function() {
# http://stackoverflow.com/questions/1815606/rscript-determine-path-of-the-executing-script
# must work with source()
if (!is.null(res <- .thisfile_source())) res
else if (!is.null(res <- .thisfile_rscript())) dirname(res)
# http://stackoverflow.com/a/35842176/2292993
# RStudio only, can work without source()
else dirname(rstudioapi::getActiveDocumentContext()$path)
}
# Helper functions
.thisfile_source <- function() {
for (i in -(1:sys.nframe())) {
if (identical(sys.function(i), base::source))
return (normalizePath(sys.frame(i)$ofile))
}
NULL
}
.thisfile_rscript <- function() {
cmdArgs <- commandArgs(trailingOnly = FALSE)
cmdArgsTrailing <- commandArgs(trailingOnly = TRUE)
cmdArgs <- cmdArgs[seq.int(from=1, length.out=length(cmdArgs) - length(cmdArgsTrailing))]
res <- gsub("^(?:--file=(.*)|.*)$", "\\1", cmdArgs)
# If multiple --file arguments are given, R uses the last one
res <- tail(res[res != ""], 1)
if (length(res) > 0)
return (res)
NULL
}
Pourquoi ne pas utiliser les commandes system et Shell? Avec Windows one, je pense que lorsque vous ouvrez le script dans RStudio, le répertoire Shell actuel est défini sur le répertoire du script. Vous devrez peut-être ajouter cd C:\eg ou le lecteur que vous souhaitez rechercher (par exemple, Shell ('dir C: \\ * nom_fichier/s', intern = TRUE) - \\ pour échapper au caractère d'échappement). Ne fonctionnera que pour les fichiers portant un nom unique, sauf si vous spécifiez davantage les sous-répertoires (pour Linux, j'ai commencé la recherche à partir de /). Dans tous les cas, si vous savez comment trouver quelque chose dans le shell, cela fournit une disposition pour le trouver dans R et retourner le répertoire. Devrait fonctionner si vous sourcez ou exécutez le script mais je n'ai pas complètement exploré les bugs potentiels.
#Get operating system
OS<-Sys.info()
win<-length(grep("Windows",OS))
lin<-length(grep("Linux",OS))
#Find path of data directory
#Linux Bash Commands
if(lin==1){
file_path<-system("find / -name 'file_name'", intern = TRUE)
data_directory<-gsub('/file_name',"",file_path)
}
#Windows Command Prompt Commands
if(win==1){
file_path<-Shell('dir file_name /s', intern = TRUE)
file_path<-file_path[4]
file_path<-gsub(" Directory of ","",file_path)
filepath<-gsub("\\\\","/",file_path)
data_directory<-file_path
}
#Change working directory to location of data and sources
setwd(data_directory)
Merci pour la fonction, même si j'ai du ajuster un peu comme suit pour moi (W10):
#Windows Command Prompt Commands
if(win==1){
file_path<-Shell('dir file_name', intern = TRUE)
file_path<-file_path[4]
file_path<-gsub(" Verzeichnis von ","",file_path)
file_path<-chartr("\\","/",file_path)
data_directory<-file_path
}