Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine path of the executing script

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

#!/usr/bin/env Rscript
message("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?

like image 639
Frank Avatar asked Oct 15 '22 19:10

Frank


People also ask

How do I find the path of a shell script?

How do I find out the current directory location and shell script directory location in Bash running on Linux or Unix like operating systems? basename command – Display filename portion of pathname. dirname command – Display directory portion of pathname.

What is path in script?

PATH is a colon separated list of directories: $ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin. The shell will look through these directories in order for the given command.

How do I find the path of a file in Bash?

In bash, there are a number of ways of retrieving the full address of a script. In particular, we can use realpath, readlink, or even create our custom little script. When we want to know the directory path, we can use the dirname command in our bash script to retrieve our directory path.

How do I run a full path in a shell script?

To use full path you type sh /home/user/scripts/someScript . sh /path/to/file is different from /path/to/file . sh runs /bin/sh which is symlinked to /bin/dash . Just making something clear on the examples you see on the net, normally you see sh ./somescript which can also be typed as `sh /path/to/script/scriptitself'.


3 Answers

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.

like image 116
this.is.not.a.nick Avatar answered Oct 19 '22 01:10

this.is.not.a.nick


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.

like image 80
Suppressingfire Avatar answered Oct 19 '22 01:10

Suppressingfire


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))
        }
}
like image 60
steamer25 Avatar answered Oct 19 '22 00:10

steamer25