bschneidr
bschneidr

Reputation: 6278

R - Create filepath relative to specific file

Let's say I have two files in different directories:

  1. Scripts/Script.R.
  2. Templates/Template.docx

If these paths are both relative to the same directory, then the path of the second file relative to the first is "../Templates/Template.docx".

Using R, how can I construct relative filepaths like this in an automated way (i.e. using a function)?

Ideally, I'm hoping there's a function that looks something like the following:

> rel_path(path = 'Templates/Template.docx', 
           rel_to = 'Scripts/Script.R')

[1] "../Templates/Template.docx"

Upvotes: 2

Views: 225

Answers (1)

Samuel
Samuel

Reputation: 144

Here is a function I wrote that does that. You need to specify the directory (main_dir) that contains both files.

rel_path <- function(target_file, ref_file, main_dir){
 ## Returns the path of a file relative to a given path within a given directory.
  # Args:
  #   target_file: name of the file for which the relative path is to be returned.
  #   ref_file: name of the reference file.
  #   main_dir: path of the directory that encompases both the target and the reference files.
  #
  # Returns:
  #   String with the relative file path. 
  #

  target_path <- list.files(path = main_dir,
                            pattern = target_file,
                            recursive = TRUE)

  ref_path <- list.files(path = main_dir,
                         pattern = ref_file,
                         recursive = TRUE)


  ## Split paths into strings to check if they have common sub directories
  ref_str <- (strsplit(ref_path,"/|\\\\")[[1]])
  tar_str <- (strsplit(target_path,"/|\\\\")[[1]])

  ## compare 
  max_len <- min(length(tar_str), length(ref_str))
  matched <- which(ref_str[1:max_len] == tar_str[1:max_len])

  if (length(matched)==0){
    matched = 0
  }

  if (length(ref_str) == 1){ ## The reference file is not inside a sub directory
    rel_path = file.path(target_path)
  }else if (length(matched) == length(tar_str) && length(tar_str) == length(ref_str) ){
    rel_path = file.path(target_file)
  }else if (max(matched) == 1){ ## Both files are under same sub directory 
    rel_path = file.path(target_path)
  }else if (sum(matched) == 0){
    count_up <- paste0(rep("..", length(ref_str)-1), collapse = "/")

    rel_path = file.path(count_up, target_path)
  }else{ ## files under different sub directory
    count_up <- paste0(rep("..", max(matched)-1), collapse = "/") 
    rel_path = paste0(c(count_up, 
                        paste0(tar_str[3:length(tar_str)], collapse = "/")),
                      collapse = "/")
  }

  return(rel_path)
}

This should then work provided that both are under the directory folder1.

> rel_path(target_file= 'Template.docx', 
           ref_file = 'Script.R', main_dir = 'folder1')

[1] "../Templates/Template.docx"

Upvotes: 2

Related Questions