views:

498

answers:

4

I have a script called foo.R that includes another script other.R, which is in the same directory:

#!/usr/bin/env Rscript
print("Hello")
source("other.R")

But I want R to find that other.R no matter what the current working directory.

In other words, foo.R needs to know its own path. How can I do that?

+1  A: 

You can wrap the r script in a bash script and retrieve the script's path as a bash variable like so:

#!/bin/bash
     # [environment variables can be set here]
     path_to_script=$(dirname $0)

     R --slave<<EOF
        source("$path_to_script/other.R")

     EOF
ennuikiller
+2  A: 

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 <- paste(sep="/", 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.

Suppressingfire
What's with the downmod?
Suppressingfire
I 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!
hadley
But actually, it does work fine with source! Just source(other.name) and it works properly.
Suppressingfire
I think maybe we're talking at cross purposes. I think we have different understandings of what the dehmann is interested in doing.
Suppressingfire
A: 

Assuming you are on Linux, you can try this:

#!/usr/bin/env Rscript
print("Hello")
source(paste(getwd(),"/other.R",sep=""))
Hrishi Mittal
I don't think that's what I want. It will give me the current dir, which is the one the script is called from, not the dir where the script is.
+3  A: 
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 :/

hadley
In what context does that work? print(sys.frames()) turns up NULL when I run it.
Suppressingfire
@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 an `ofile` member.
Richie Cotton
You 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
I tried putting it in a file with #!/usr/bin/env Rscript at the top, but that didn't help either. Also, I don't have a Negate() function in my R version 2.6.2.
Suppressingfire
R 2.6.2. is almost two years old. Get a newer version!
hadley
This does not answer my question. I need to automatically find the "other.R" file. `x$ofile` is undefined, so `frame_files` is empty.