juba
juba

Reputation: 49033

Split a file path into folder names vector

In R, with file.path, you can convert a character vector into a full file path, automatically using the correct file separator for your platform :

> file.path("home", "foo", "script.R")
[1] "home/foo/script.R"

I'd like to do exactly the reverse : split a file path into a character vector of components. So far I almost manage to do it with a recursive function, but I don't find it very elegant :

split_path <- function(file) {
  if(!(file %in% c("/", "."))) {
    res <- c(basename(file), split_path(dirname(file)))
    return(res)
  }
  else return(NULL)
}

Which gives :

> split_path("/home/foo/stats/index.html")
[1] "index.html" "stats"      "foo"        "home" 

Do you know of any already existing function, or at least a better way to do such a thing ?

Thanks !

EDIT : I think I'll finally stick to this slightly different recursive version, thanks to @James, which should handle drive letters and network shares under Windows :

split_path <- function(path) {
  if (dirname(path) %in% c(".", path)) return(basename(path))
  return(c(basename(path), split_path(dirname(path))))
}

Upvotes: 15

Views: 13514

Answers (4)

S&#248;ren ONeill
S&#248;ren ONeill

Reputation: 529

Check out the path_split function of the fs package !

Upvotes: -1

Losses Don
Losses Don

Reputation: 983

you can use the package DescTools to solve the problem:

library(DescTools)

SplitPath('C:/users/losses/development/R/loveResearch/src/signalPreprocess.R')

The output is:

$normpath
[1] "C:\\users\\losses\\development\\R\\loveResearch\\src\\signalPreprocess.R"

$drive
[1] "C:"

$dirname
[1] "/users/losses/development/R/loveResearch/src/"

$fullfilename
[1] "signalPreprocess.R"

$filename
[1] "signalPreprocess"

$extension
[1] "R"

Pretty convenient.

Upvotes: 5

James
James

Reputation: 66814

You can do it with a simple recursive function, by terminating when the dirname doesn't change:

split_path <- function(x) if (dirname(x)==x) x else c(basename(x),split_path(dirname(x)))
split_path("/home/foo/stats/index.html")
[1] "index.html" "stats"      "foo"        "home"       "/" 
split_path("C:\\Windows\\System32")
[1] "System32" "Windows"  "C:/"
split_path("~")
[1] "James"  "Users" "C:/" 

Upvotes: 17

Dominic Comtois
Dominic Comtois

Reputation: 10401

Try this (will work with both "/" and "\"):

split_path <- function(path) {
    rev(setdiff(strsplit(path,"/|\\\\")[[1]], ""))
} 

Results

split_path("/home/foo/stats/index.html")
# [1] "index.html" "stats"      "foo"        "home"

rev(split_path("/home/foo/stats/index.html"))
# [1] "home"       "foo"        "stats"      "index.html"

Edit

Making use of normalizePath, dirname and basename, this version will give different results:

split_path <- function(path, mustWork = FALSE, rev = FALSE) {
    output <- c(strsplit(dirname(normalizePath(path,mustWork = mustWork)),
                                             "/|\\\\")[[1]], basename(path))
    ifelse(rev, return(rev(output)), return(output))
}

split_path("/home/foo/stats/index.html", rev=TRUE)
# [1] "index.html" "stats"      "foo"        "home"       "D:" 

Upvotes: 9

Related Questions