Reputation: 49033
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
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
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
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