How to set the current file location as the default working directory in R programming?

21.9k views Asked by At

I want to make the current file location as the working directory.

Using Rstudio (Works!):

# Author  : Bhishan Poudel
# Program : writehere.r
# Source  : Rscript writehere.r

# set working directory here
this.dir <- dirname(parent.frame(2)$ofile) # frame(3) also works.
setwd(this.dir)

# Sample data to test this code
mydata <- seq(1:10)
write.csv(mydata,"writehere.dat")
#This works flawlessly in  MacOS 10.9 and Ubuntu 15.1.

Using Command from terminal : Rscript writehere.r (Does not work!)

Error in dirname(parent.frame(2)$ofile) : 
  a character vector argument expected
Execution halted


------------------
(program exited with code: 1)

Using Command from terminal : Rscript writehere.r (Works now!)

# Author  : Bhishan Poudel
# Program : writehere.r
# Source  : Rscript example.r

# set working directory here
this_dir <- function(directory)
setwd( file.path(getwd(), directory) )

# Sample data to test this code
mydata <- seq(1:10)
write.csv(mydata,"writehere.dat")

Using function inside ~/.Rprofile for Rstudio (Works!) :,

##############################################
# inside ~/.Rprofile
# set up working directory
setwd_thisdir <- function () {
  this.dir <- dirname(parent.frame(3)$ofile)
  setwd(this.dir)
} 
##############################################

Then, in any directory let's say I have a file writehere.r, now it works.

# Author  : Bhishan Poudel
# Program : writehere.r
# Compile : Rscript writehere.r

# set working directory here
setwd_thisdir

# Sample data to test this code
mydata <- seq(1:10)
write.csv(mydata,"writehere.dat")

Question: Why the function

this.dir <- dirname(parent.frame(2)$ofile) # frame(3) also works.
setwd(this.dir)

does not work for text editors other than Rstudio?

Some useful links are following:
R setting working directory to source file location?
R command for setting working directory to source file location
get filename and path of `source`d file
setwd() in the current working dir
Command for "Set working directory to source file location"
SublimeText and R: Setting Current File Directory
Setting working directory through a function
What is a fool-proof way of permanently setting R working directory?
R setting working directory to source file location?
How to get into the directory of a file in R?

5

There are 5 answers

0
Suresh Gautam On

Simply, use rstudio API, extract its directory, and set it as a working directory as shown below:

setwd(dirname(rstudioapi::getSourceEditorContext()$path))

Verify if you set the directory correctly by the following command:

getwd()
0
Lars Arne Jordanger On

UPDATE: I realised that this answer didn't help at all, and I will post another one that does the trick.

Insofar the code you want to run doesn't need any additional arguments, a solution as sketched below, using eval(expr, envir) might do the trick.

Consider the following example using print(environment()), which should return environment: R_GlobalEnv when used on the command line. The function test_1 will print information about the internal environment that is created when the function is called, whereas the function test_2 will return the desired result.

test_1 <- function(){
     print(environment())
}

test_2 <- function(){
    .expr <- quote({
        print(environment())
        })
    .envir <- sys.frame(which = -1)
    eval(expr = .expr,
         envir = .envir)
}

The sys.frame(which = -1) ensures that the expression is evaluated in the environment where the function is called. If you are certain that you always want to use the global environment, then it's better to use .GlobalEnv. It's also important to quote the expression you want to use, otherwise it might not work as desired.

A nice feature of this solution is that you don't need to tweak the code you want to put into the function, just quote it.

Finally: It's possible to extend this approach such that your function can take arguments that then will be given to the code you want to evaluate in another environment. This will however require a bit of non-trivial tweaking upon the expression you want to evaluate; you might need to use the bquote + .() construction - and you might in addition also need to use call and do.call.

0
Lars Arne Jordanger On

The first answer I gave missed the point completely, since I hadn't looked closely upon what you wanted to achieve. The solution presented here should however do the trick.

First note that source has an argument chdir that in the help-file is described with: logical; if TRUE and file is a pathname, the R working directory is temporarily changed to the directory containing file for evaluating.

To manually specify that argument every time you want to source a file would be a pain, so let's add something to .Rprofile that changes the default value for chdir from FALSE to TRUE.

The formals-function can be used to modify a default value, but when used upon a function that belongs to some other environment, the result will be that a local copy of the function will be created instead. That's not good enough.

It's probably several ways to resolve this, but the following little hack of source did the trick for me when I inserted it into .Rprofile.

.temporary_copy_source <- base::source
formals(.temporary_copy_source)$chdir <- TRUE
utils::assignInNamespace(
    x = "source",
    value = .temporary_copy_source,
    ns = environment(source))
rm(.temporary_copy_source)

A word of warning: The method presented here can in principle allow users to modify the default values of any argument in any function, but that would be an exceptionally bad idea to do. Keep in mind that your scripts might later on be shared with someone that doesn't have the same .Rprofile that you have. Never write code that requires such modifications of the namespaces!

0
user7669 On

I write another answer because you changed your question. There are two useful facts:

  1. ofile is a variable in the environment of the source function, so you can use it only when you run some script with the source function.
  2. When you run a script from the terminal, then the working directory is set to the current directory in the terminal.

So, to comment on your observations:

  1. Using Rstudio (Works!). Yes if you press Source (which usues the source function), but not if you press Run (which just runs the commands in the R console).
  2. Rscript writehere.r (Does not work!). That's because you are looking for ofile without a call to source.
  3. Rscript writehere.r (Works now!). Yes, but it works just by fact 2: the code this_dir <- function(directory) setwd( file.path(getwd(), directory) ) is needless as it is just the definition of a function called this_dir.
  4. Rstudio (Works!). First part: OK. Second part. It works just by fact 2. In particular setwd_thisdir is needless because it just prints the body of setwd_thisdir to the console.

In summary setwd(dirname(parent.frame(2)$ofile)) is a useful trick when you source a script with the source function, but don't have access to the source function options: e.g. when you press Source in R-Studio. When possible use intead the source function with chdir=TRUE. If you run the script form the terminal just set the terminal to the script folder.

0
user7669 On

Try using parent.frame(3) in you function:

setwd_thisdir <- function () {
  this.dir <- dirname(parent.frame(3)$ofile)
  setwd(this.dir)
}

See ?parent.frame or http://adv-r.had.co.nz/Environments.html#calling-environments.

You may also look at the chdir option of the source function (?source).