Есть ли что-то похожее на make.path.relative(base.path, target.path)
?Функция для построения относительных путей в R?
Я хочу преобразовать полные пути в относительные пути, заданные базовым путем (например, каталог проекта).
Есть ли что-то похожее на make.path.relative(base.path, target.path)
?Функция для построения относительных путей в R?
Я хочу преобразовать полные пути в относительные пути, заданные базовым путем (например, каталог проекта).
Похожие, но короче:
make.path.relative = function(base, target) {
common = sub('^([^|]*)[^|]*(?:\\|\\1[^|]*)$', '^\\1/?', paste0(base, '|', target))
paste0(gsub('[^/]+/?', '../', sub(common, '', base)),
sub(common, '', target))
}
make.path.relative('C:/home/adam', 'C:/home/adam/tmp/R')
#[1] "tmp/R"
make.path.relative('/home/adam/tmp', '/home/adam/Documents/R')
#[1] "../Documents/R"
make.path.relative('/home/adam/Documents/R/Project', '/home/adam/minetest')
#[1] "../../../minetest"
Voodoo регулярное выражение приходит from here.
Ok. Я написал функцию себя:
make.path.relative<-function(base.path, target.path)
{
base.s<-strsplit(base.path,'/',fixed=TRUE)[[1]]
target.s<-strsplit(target.path,'/',fixed=TRUE)[[1]]
idx<-1
maxidx<-min(length(target.s),length(base.s))
while(idx<=maxidx)
{
if (base.s[[idx]]!=target.s[[idx]])
break
idx<-idx+1
}
dotscount<-length(base.s)-idx+1
ans1<-paste0(paste(rep('..',times=dotscount),collapse='/'))
if (idx<=length(target.s))
ans2<-paste(target.s[idx:length(target.s)],collapse='/')
else
ans2<-''
ans<-character(0)
if (ans1!='')
ans[[length(ans)+1]]<-ans1
if (ans2!='')
ans[[length(ans)+1]]<-ans2
ans<-paste(ans,collapse='/')
return(ans)
}
Вы должны сначала дезинфицировать пути, чтобы убедиться, что они используют один и тот же слэш конвенции. Вы можете использовать функцию path.cat из моего ответа на Function to concatenate paths?
Примеры:
> make.path.relative('C:/home/adam', 'C:/home/adam/tmp/R')
[1] "tmp/R"
> make.path.relative('/home/adam/tmp', '/home/adam/Documents/R')
[1] "../Documents/R"
> make.path.relative('/home/adam/Documents/R/Project', '/home/adam/minetest')
[1] "../../../minetest"
Если target.path всегда является дочерним объектом base.path, вы можете легко свернуть свою собственную функцию с помощью basename() и dirname() http://stackoverflow.com/q/2548815/1191259 – Frank
@Frank Это будет не обязательно быть правдой в будущем, но это хорошая отправная точка. Спасибо! –