2016-04-19 8 views
4

Есть ли что-то похожее на make.path.relative(base.path, target.path)?Функция для построения относительных путей в R?

Я хочу преобразовать полные пути в относительные пути, заданные базовым путем (например, каталог проекта).

+1

Если target.path всегда является дочерним объектом base.path, вы можете легко свернуть свою собственную функцию с помощью basename() и dirname() http://stackoverflow.com/q/2548815/1191259 – Frank

+1

@Frank Это будет не обязательно быть правдой в будущем, но это хорошая отправная точка. Спасибо! –

ответ

1

Похожие, но короче:

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.

1

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" 
Смежные вопросы