Determine path of the executing script
Solution 1
Here there is a simple solution for the problem. This command:
script.dir <- dirname(sys.frame(1)$ofile)
returns the path of the current script file. It works after the script was saved.
Solution 2
You can use the commandArgs
function to get all the options that were passed by Rscript to the actual R interpreter and search them for --file=
. If your script was launched from the path or if it was launched with a full path, the script.name
below will start with a '/'
. Otherwise, it must be relative to the cwd
and you can concat the two paths to get the full path.
Edit: it sounds like you'd only need the script.name
above and to strip off the final component of the path. I've removed the unneeded cwd()
sample and cleaned up the main script and posted my other.R
. Just save off this script and the other.R
script into the same directory, chmod +x
them, and run the main script.
main.R:
#!/usr/bin/env Rscript
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)
other.name <- file.path(script.basename, "other.R")
print(paste("Sourcing",other.name,"from",script.name))
source(other.name)
other.R:
print("hello")
output:
burner@firefighter:~$ main.R
[1] "Sourcing /home/burner/bin/other.R from /home/burner/bin/main.R"
[1] "hello"
burner@firefighter:~$ bin/main.R
[1] "Sourcing bin/other.R from bin/main.R"
[1] "hello"
burner@firefighter:~$ cd bin
burner@firefighter:~/bin$ main.R
[1] "Sourcing ./other.R from ./main.R"
[1] "hello"
This is what I believe dehmann is looking for.
Solution 3
I couldn't get Suppressingfire's solution to work when 'source'ing from the R console.
I couldn't get hadley's solution to work when using Rscript.
Best of both worlds?
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))
}
}
Solution 4
frame_files <- lapply(sys.frames(), function(x) x$ofile)
frame_files <- Filter(Negate(is.null), frame_files)
PATH <- dirname(frame_files[[length(frame_files)]])
Don't ask me how it works though, because I've forgotten :/
Solution 5
This works for me
library(rstudioapi)
rstudioapi::getActiveDocumentContext()$path
Related videos on Youtube
Frank
Updated on May 05, 2022Comments
-
Frank about 2 years
I have a script called
foo.R
that includes another scriptother.R
, which is in the same directory:#!/usr/bin/env Rscript message("Hello") source("other.R")
But I want
R
to find thatother.R
no matter what the current working directory.In other words,
foo.R
needs to know its own path. How can I do that?-
Frank over 14 yearsNo. :( I haven't seen any solution that actually works. Apart from the workaround to just pass the directory in or use an environment variable.
-
Frank over 14 yearsI hate having to rely on environment variables.
-
aL3xa almost 14 yearsTry with
system("locate other.R")
... but be sure to give your script a unique name... O_o (assuming that you use UNIX system and thatlocate
command is available) -
Etienne Low-Décarie about 12 yearsThis would be amazing to make scripts fully portable and executable by even R neofites!
-
Etienne Low-Décarie about 12 yearsIt appears like all the answers require you to input the path at some point (at least to source the file)! It would be great if you could send someone a compressed folder and running any R script file within that folder would read from and save to that folder.
-
Giacomo over 6 yearsthis single issue could actually become te reason why I could completely move to Python
-
Michael Barton over 6 years@giac_man, I feel R is full of hundreds of tiny problems like this that all add up to making very difficult to work in.
-
mjs over 4 yearsin Matlab there is the magic command 'mfilename' swich gives you the file name of currently running code. It cannot be so difficult to add something like that in R!
-
M_Merciless over 3 yearsGreat package from @Andrew , perfect for logging purposes. Many thanks for putting this on CRAN.
-
-
Suppressingfire over 14 yearsIn what context does that work? print(sys.frames()) turns up NULL when I run it.
-
Richie Cotton over 14 years@Suppressingfire:
sys.frames
returns the environments of the call stack, so it only really makes sense when called from a function. Try, e.g.,foo <- function() {bar <- function() print(sys.frames()); bar()}; foo()
. I can't figure out @hadley's code though because environments don't have anofile
member. -
hadley over 14 yearsYou have to source the file in - i.e. if I save that code then run
source("~/code/test.r")
,PATH
will be set to~/desktop
. If you just evaluate it at the top level, it will return NULL. -
hadley over 14 yearsI downmodded because your technique doesn't work with
source
as I thought the OP wanted - but maybe I misread his/her requirement. But I can't un-downmod :( Sorry! -
Suppressingfire over 14 yearsBut actually, it does work fine with source! Just source(other.name) and it works properly.
-
Suppressingfire over 14 yearsI think maybe we're talking at cross purposes. I think we have different understandings of what the dehmann is interested in doing.
-
Frank over 14 yearsThis does not answer my question. I need to automatically find the "other.R" file.
x$ofile
is undefined, soframe_files
is empty. -
Etienne Low-Décarie about 12 yearsThis requires you to have the script path. It does not allow you to make a truly portable R script that can run from anywhere.
-
Sim almost 12 years@hadley, very useful code. I was able to generalize the "reload current script" utility function I add to almost all scripts when they are in active development. RScript reloader
-
Jason over 9 yearsFor path concatenation, better to use
other.name <- file.path(script.basename, "other.R")
-
Ehsan88 over 9 yearsIt doesn't work for me. I run R in Windows. Any idea?
-
this.is.not.a.nick over 9 yearsYou always have to save the document befor running the script. Maybe is this the problem.
-
wch over 9 yearsI like this because it works with both
Rscript
andsource()
within R. I'd suggest doingnormalizePath()
on both versions, so that it gives the full path in both cases. -
The Unfun Cat about 9 yearsThis did not work recursively; the file I source looks for a data file (but in the wrong directory).
-
RalfB almost 9 yearsGot the same error, with a saved scriptt and freshly installed and run R 3.2.0 on windows...
-
Murta almost 9 yearsThis error happens when you try to execute
dirname(sys.frame(1)$ofile)
directly from Rstudio. It works ok when the script is executed using source("other.R"), anddirname(sys.frame(1)$ofile)
is inside"other.R"
. -
Ahmed Laatabi over 8 yearsit's working under Mac.. this should be executed from a script file, nit directly from R terminal
-
user9869932 over 8 yearsThis option works fine in Mac with R-Studio. Thank-you!
-
Mark Adamson about 8 yearsI got the 'not that many frames on the stack' error when calling as a script with rscript.exe i.e. not using source(). so I had to instead use the solution from Suppressingfire below
-
jcarlos about 8 yearsFor me, your solution was the best. Specially because it could be applied to a Shiny app and that one on link not.
-
davidski almost 8 yearsDid not work for me as well (Win10, fresh R.3.3.0, ran from cmd line). Answer from @Suppressingfire below worked fine.
-
Mark Adamson almost 8 yearsThis doesn't work when using debugSource as the relevant property is then fileName rather than oFile. Just needs some simple if statements to get around it as shown in other solutions posted here like stackoverflow.com/a/32016824/538403
-
Mark Adamson almost 8 yearssource in Rstudio gave ofile for me, but debugSource gave fileName so your solution works well but the code comments aren't quite right in my case
-
O.rka over 7 yearsThis is the only thing that worked. Note, for this to work
library(base)
took me a while to figure that out lol -
RubenLaguna over 7 yearsHere the getSrcDirectory is utils::getSrcDirectory
-
user1071847 over 7 yearsNope. That finds the directory of the process, not the file itself.
-
Paul over 7 yearsI gel
NULL
when this is placed in server.R when using shiny -
Paul over 7 yearsWhen I try to run
commandArgs(trailingOnly = FALSE)
inside server.R in a shiny application, I get[1] "RStudio" "--interactive"
. No information about the directory it was called from. -
PeterVermont about 7 yearsI do not see
ofile
but do seefileName
-
geneorama almost 7 yearsThis worked for me in windows, in linux, but then it failed when I called it from crontab. SAD!
-
ManicMailman almost 7 yearsDoesn't work with interactive R session; I'm getting: ``` > source("csf.R") > csf() Error: RStudio not running ```
-
theforestecologist almost 7 yearswhat is "ofile"??
-
Contango almost 7 yearsThis might work nicely under Linux/Mac, but it did not work for me in an interative RStudio session under Windows.
sourceDir
was blank. -
Contango almost 7 yearsThis worked for me in Windows with RStudio in interactive mode.
-
John Haberstroh over 6 years@EtienneLow-Décarie It does not require the script path, it gets it from bash. The main issue is that it is not a reliable way to get the path. Something like this is preferred, as in stackoverflow.com/questions/59895/… path_to_script="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-
Michael Barton over 6 yearsI still get the error "Error in sys.frame(1) : not that many frames on the stack "
-
nJGL over 6 yearsNot from within RStudio, though, except when sourcing
-
Pranasas over 6 yearsAfter all these years I consider this to be the best and cleanest answer.
-
pommedeterresautee over 6 years@Contango on an interactive terminal, there is no path!!! You want the path to a file.
-
Ufos over 6 yearsSOLUTION:
user@laptop_model:~$ R -e 'source("/home/user/[path_to_file].R")'
-- relative paths work like magic -
bokov about 6 yearsIt always returns NA, even if I create a script that prints its output and then call the script e.g. with
R -e "library(getopt); testscript.R"
-
Ryan C. Thompson about 6 yearsAs the name of the function implies, you need to run your script using
Rscript
. -
bokov about 6 yearsAh, oops. Thanks.
-
Vince W. about 6 yearsyou sir get my vote, because this is the solution that worked for me
-
Ista over 5 yearsThis only works from inside RStudio I guess. Trying from the terminal I get
Error: RStudio not running
. -
quest over 5 yearsFor me this works sometimes while rest of the time I get
Error in path.expand(path) : invalid 'path' argument
error. -
Andrew about 5 yearsThis solution didn't work for me with
Rscript dir/foo.R
. It did work withR -e "source('dir/foo.R')"
. -
Kim about 5 yearsIf this helps anyone, for the original post, that would mean
source(file.path(dirname(thisFile()), "other.R"))
infoo.R
. This works for me. -
Bojan P. almost 5 years
Package ‘scriptName’ was removed from the CRAN repository.
- what now? :o -
Wassadamo almost 5 yearsOne issue. Suppose in RStudio I source
main.R
which sourceshelper.R
which callsthisFile()
. It will fetch the path ofmain.R
instead ofhelper.R
. Any tips here? -
abalter almost 5 yearsI'm getting
character(0)
. Suggestions? -
Ron over 4 yearsFor me the here package do exactly the job and seems to be an easy solution
-
Boops Boops over 4 yearsThis did not work for me on a Linux machine; instead of returning the path of the file, it returned the directory I was currently located in. I created a test script called TEST.R with one line of code: print(fileSnapshot()$path) I saved it in this folder: /opt/home/boops/Desktop/Testfolder/TEST.R I then navigated to my desktop and tried to run the file: boops@linuxserver:~/Desktop$ Rscript /opt/home/boops/Desktop/Testfolder/TEST.R [1] "/opt/home/boops/Desktop"
-
Colombo about 4 yearsAs I just figured what I want on how sys.frames work from previous answer, I have found this solution.
sys.frames()
will get stack of environment from the most recent to the oldest one. This includesource
, which will set theofile
atribute, and non sourced environment, such as functions, which do not haveofile
atribute. This will simply find the latest environment with theofile
atribute. Brilliant. -
altabq about 4 yearsI get an error message
readLink: illegal option -- e usage: readLink [-FlLnqrsx] [-f format] [-t timefmt] [file ...]
-
Kay almost 4 yearsmore specifically it works, if run from a R script in R studio. Even on the console in RStudio it will not give the right result
""
in my case -
Joe Flack almost 4 yearsDidn't work for me either. Returns the same thing as 'here()' when using the 'here' library. It returned the path to my currently open R project, but not he very file itself being executed.
-
Joe Flack almost 4 yearsThis is great. Can someone make a package?
-
Patrick almost 4 yearsThis works while running interactively in Rstudio as long as you don't change the document in focus. If you submit lines to run and then switch to another document while they run, the path to the other document will be returned.
-
Patrick almost 4 yearsThis works while running interactively in Rstudio as long as you don't change the document in focus. If you submit lines to run and then switch to another document while they run, the path to the other document will be returned.
-
Andrew over 3 yearsI've uploaded a package named "this.path" to CRAN, it should solve this issue!
-
johnny over 3 yearsWhen running this command on RGui, I get the following message. Any idea on how to get around it? Error in this.path::this.path() : 'this.path' used in an inappropriate fashion * no appropriate 'source' or 'sys.source' call was found up the calling stack * R is being run from RGui which requires a 'source' and 'sys.source' call on the calling stack
-
Andrew over 3 yearsI hadn't realized until you commented that you could run code from within a script from 'RGui', I thought previously that the only way to run code within a script from 'RGui' was to use 'source'. I'm looking into a fix for this issue, hopefully I'll find something soon. For now, you could use 'RStudio' to edit and run your scripts because I know it works from there. Sorry for the lack of an answer, but thank you for pointing out this bug!
-
Andrew over 3 years@johnny I believe I found a solution, but it only works on a Windows OS. I'm attempting to find a solution for the macOS version of "RGui" named "AQUA", and then I'll upload the update to the package to CRAN. It'll be about ~10 business days before the update is approved for release by one of the CRAN maintainers, hopefully 'RStudio' is working for you in the meantime!
-
Andrew over 3 years@johnny the update was released a few hours ago, much sooner than I was expecting. I've tested on two separate computers now, it seems to work as intended from 'RGui'!
-
johnny over 3 yearsJust tested v.0.2.0 on a script file saved in an RGui session, and it works for me. Thanks!
-
Andrew over 3 years@JoeFlack I've made a package for this called "this.path", you can find it on CRAN at CRAN.R-project.org/package=this.path
-
Andrew over 3 yearsThis only works when using
source
orsys.source
, and it always grabs the firstsource
on the stack, not the most recent. -
Andrew over 3 years@Wassadamo you could try package "this.path", it handles nested source calls correctly
-
Andrew over 3 yearsfileSnapshot()$path just returns the path of the current working directory, not the path of the executing script. Another thing, on Windows it is unnecessary to substitute the backslashes with forward slashes, but on a Unix-alike OS it is dangerous to do this since filenames can contain backslashes. Last thing, you should not have a path separator at the end of your path since R will no longer recognize the string as a path (as returned by 'file.exists').
-
user5359531 over 2 yearsThis is the correct answer. Really baffling how many people are wasting time with the other proposed answers to this.
-
htlbydgod about 2 yearsThis does not work for me on Mac
-
understorey almost 2 yearsIn windows/Rstudio it returns
character(0)
-
understorey almost 2 yearsThis does not work for me in RStudio/Windows from
sys.frames()[[1]]$ofile
I getNULL
.