2

I have a function that looks like this:

read_data <- function(filename, header) {
  path <- paste("./output/", filename, sep = "")
  if (file.exists(path)) {
      data <- read.csv(file = path, header = header, sep = ",")
  }
  # Partially removed for brevity.
}

What I want to achieve is that, given a filename, I want to search whether that filename is available inside the output subdirectory, which is a subdirectory where my script is located, and if it is available, I want to read that file. The problem is that as long as I know read.csv function's file argument requires a full path for the file. So, I somehow need to get the directory where my script is located, so I can concatenate it with the rest of the subdirectory and filename. I can get the current working directory with getwd(), but that's not quite the same thing, as my working directory seems always to be fixed, whereas the script can be located anywhere in the computer. Any ideas how to get the directory of the script, and concatenate it with the output subdirectory and the provided filename in R?

tinker
  • 2,884
  • 8
  • 23
  • 35
  • Check out `list.files()` I think that may solve your problem. – Badger Mar 09 '18 at 15:11
  • The `file.exists` function tells you whether a file exists. – nicola Mar 09 '18 at 15:18
  • `file.exist` on a path may not get you what you're looking for. You could add a file.exists wrapper around the `list.files` example I gave you below, but it may be easier to just read everything in, the blanks would correspond to the filename element number. – Badger Mar 09 '18 at 15:27
  • It's not clear to me what you are trying to do. Do you want to know the full path of a file just knowing its basename? – nicola Mar 09 '18 at 15:28
  • @nicola Let's say this script is called `myscript.R` and it is located in `C:\User\myUser\Desktop\myscript.R`, and assume that R by default has `C:\User\myUser` as the current working directory. So, what I want to do is that inside this `myscript.R` I want to have some code that will get the full path where it is located in the hard disk, which is `C:\User\myUser\Desktop\myscript.R` in this example. – tinker Mar 09 '18 at 15:31
  • OOOOOO Well that isn't your question ;) I'm interpreting this as: where is the location of what I am working on. The existence is irrelevant since you're working in it at that time. Is that correct? Still doesn't make sense, why do you need to determine the directory in the code? You opened the script, so you know where it is. Just type in the directory? – Badger Mar 09 '18 at 15:34

4 Answers4

2

if you want to detemine the directory of the executing script, this might be a dup: Rscript: Determine path of the executing script

initial.options <- commandArgs(trailingOnly = FALSE)
file.arg.name <- "--file="
script.name <- sub(file.arg.name, "", initial.options[grep(file.arg.name, initial.options)])
script.dirname <- dirname(script.name)
print(script.dirname)
Joerg
  • 71
  • 4
0

Adding this as an answer for you Tinker.

Considering you're just trying to read in a file you can do it this way:

## So what does this do?
# The path is where the files exist
# The pattern is some identifiable portion of the file name, which list.files() will bring back
# You need the full name so that R knows where to read from, this way you don't have to set a new working directory.


data <- if(file.exists(list.files(path = "./output/", pattern = "filename",full.names=T))){ read.csv(list.files(path = "./output/", pattern = "filename",full.names=T))}

# Let's imagine you have a number of files to read in

# Generate a list of filenames

filename <- list("file1","file2","file3","filen")

data <- lapply( filename, function(x) {
if( file.exists( list.files( path = "./output/", pattern = x ,full.names=T ) ) ) {
 read.csv( list.files(path = "./output/", pattern = x ,full.names=T) ) }
} )
    # each element of the list is oe of your data files
    data[[1]]
    data[[2]]
    data[[n]]

I'm not sure what you're declaring with header as csv's are assumed to have a header inherently, additionally a csv is comma separated so declaring the sep character is also redundant.

Badger
  • 1,043
  • 10
  • 25
  • Only if you do not declare a path, if you declare a path, it lists everything in that path. I don't recommend using `setwd()` for this very reason. it builds complacency on knowing how to call things that aren't in your current `wd`. – Badger Mar 09 '18 at 15:30
0
> f <- "/path/to/my/script.R"

> f
[1] "/path/to/my/script.R"

> basename(f)
[1] "script.R"

> dirname(f)
[1] "/path/to/my"

> dirname(dirname(f))
[1] "/path/to"

> file.path(dirname(f), "output")
[1] "/path/to/my/output"

> file.path(dirname(f), "output", "data.csv")
[1] "/path/to/my/output/data.csv"
Kamil Slowikowski
  • 4,184
  • 3
  • 31
  • 39
  • No. You might consider showing us the commands you are trying to run or describing your working environment. For example, are you executing `Rscript myscript.R` in the shell? Are you in an interactive R session? Maybe you'd be interested in the "here" package? https://github.com/krlmlr/here – Kamil Slowikowski Mar 09 '18 at 15:36
0

Collecting resources from multiple questions in SO, I came up with the following solution, that seems to work with multiple calling conventions:

library(base)
library(rstudioapi)

get_directory <- function() {
  args <- commandArgs(trailingOnly = FALSE)
  file <- "--file="
  rstudio <- "RStudio"

  match <- grep(rstudio, args)
  if (length(match) > 0) {
    return(dirname(rstudioapi::getSourceEditorContext()$path))
  } else {
    match <- grep(file, args)
    if (length(match) > 0) {
      return(dirname(normalizePath(sub(file, "", args[match]))))
    } else {
      return(dirname(normalizePath(sys.frames()[[1]]$ofile)))
    }
  }
}

Which later I can use as:

path <- paste(get_directory(), "/output/", filename, sep = "")
tinker
  • 2,884
  • 8
  • 23
  • 35