Au cas où quelqu'un le voudrait, voici ma propre fonction path.cat
. Sa fonctionnalité est comparable à celle de Python. os.path.join
avec le sucre supplémentaire, qu'il interprète le ..
.
Avec cette fonction, vous pouvez construire des chemins de manière hiérarchique, mais contrairement à la fonction file.path
vous laissez à l'utilisateur la possibilité d'ignorer la hiérarchie en mettant un chemin absolu. Et comme un sucre supplémentaire, il peut mettre le ".." où il veut dans le chemin, avec une signification évidente.
par exemple
-
path.cat("/home/user1","project/data","../data2")
yelds /home/user1/project/data2
-
path.cat("/home/user1","project/data","/home/user2/data")
yelds /home/user2/data
La fonction ne fonctionne qu'avec des barres obliques comme séparateur de chemin, ce qui est bien, puisque R les traduit de manière transparente en barres obliques inversées sur la machine Windows.
library("iterators") # After writing this function I've learned, that iterators are very inefficient in R.
library("itertools")
#High-level function that inteligentely concatenates paths given in arguments
#The user interface is the same as for file.path, with the exception that it understands the path ".."
#and it can identify relative and absolute paths.
#Absolute paths starts comply with "^\/" or "^\d:\/" regexp.
#The concatenation starts from the last absolute path in arguments, or the first, if no absolute paths are given.
path.cat<-function(...)
{
elems<-list(...)
elems<-as.character(elems)
elems<-elems[elems!='' && !is.null(elems)]
relems<-rev(elems)
starts<-grep('^[/\\]',relems)[1]
if (!is.na(starts) && !is.null(starts))
{
relems<-relems[1:starts]
}
starts<-grep(':',relems,fixed=TRUE)
if (length(starts)==0){
starts=length(elems)-length(relems)+1
}else{
starts=length(elems)-starts[[1]]+1}
elems<-elems[starts:length(elems)]
path<-do.call(file.path,as.list(elems))
elems<-strsplit(path,'[/\\]',FALSE)[[1]]
it<-ihasNext(iter(elems))
out<-rep(NA,length(elems))
i<-1
while(hasNext(it))
{
item<-nextElem(it)
if(item=='..')
{
i<-i-1
} else if (item=='' & i!=1) {
#nothing
} else {
out[i]<-item
i<-i+1
}
}
do.call(file.path,as.list(out[1:i-1]))
}