Shorten an absolute path
JavaScript (ES6), 107 106 bytes
Takes the absolute path a
and the current path c
in currying syntax (a)(c)
.
a=>c=>(A=a.split`/`,s='',c.split`/`.map(d=>!s&A[0]==d?A.shift():s+='../'),s+=A.join`/`)[a.length]?a:s||'.'
Test cases
let f =
a=>c=>(A=a.split`/`,s='',c.split`/`.map(d=>!s&A[0]==d?A.shift():s+='../'),s+=A.join`/`)[a.length]?a:s||'.'
console.log(f
('/home/user/mydir/myfile')
('/home/user')
);
console.log(f
('/var/users/admin/secret/passwd')
('/var/users/joe/hack')
);
console.log(f
('/home/user/myfile')
('/tmp/someplace')
);
console.log(f
('/dir1/dir2')
('/dir1/dir2/dir3/dir4')
);
console.log(f
('/dir1/dir2')
('/dir1/dir2')
);
Retina, 85 83 82 bytes
1 byte saved thanks to @MartinEnder
^(..+)(.*;)\1
%$2
(%?)(.*);(.*)
$1$3;$2
\w+(?=.*;)
..
%;/
;
/
.*//
/
%/?|/$
^$
.
Try it online!
Julia 0.5, 32 bytes
!,~=relpath,endof
t->~t<~!t?t:!t
This uses the current working directory as base and cannot be tested on TIO at the moment.
Example run
Warning: This will alter your file system.
$ sudo julia --quiet
julia> function test(target,base)
mkpath(base)
cd(base)
shorten(target)
end
test (generic function with 1 method)
julia> !,~=relpath,endof
(relpath,endof)
julia> shorten = t->~t<~!t?t:!t
(::#1) (generic function with 1 method)
julia> test("/home/user/mydir/myfile","/home/user")
"mydir/myfile"
julia> test("/var/users/admin/secret/passwd","/var/users/joe/hack")
"../../admin/secret/passwd"
julia> test("/home/user/myfile","/tmp/someplace")
"/home/user/myfile"
julia> test("/dir1/dir2","/dir1/dir2/dir3/dir4")
"../.."
julia> test("/dir1/dir2","/dir1/dir2")
"."
Alternate version, 35 bytes (dyadic)
^,~=relpath,endof
t-b=~t<~t^b?t:t^b
This takes the base directory as input, so it can be tested without modifying the file system.
Try it online!