
Suppose that I'm in foo/bar/box1/top and I want to access a file in foo/bar/box2/side. How do I construct the shortest possible relative path from one to the other? The filepath package doesn't seem to provide a function to do this. (The correct answer is obviously "../../box2/side" in this instance, but how do I compute that in general?)

On Saturday 11 September 2010 13:20:08, Andrew Coppin wrote:
Suppose that I'm in foo/bar/box1/top and I want to access a file in foo/bar/box2/side. How do I construct the shortest possible relative path from one to the other? The filepath package doesn't seem to provide a function to do this. (The correct answer is obviously "../../box2/side" in this instance,
No. The shortest relative path might be "baz" or "../side" or ".". Links make handling file paths fun. Not. So in the presence of links, to be certain to have the shortest possible relative path, you'd have to search more or less the entire file system. And "../../box2/side" need not even be a path from "foo/bar/box1/top" to "foo/bar/box2/side" (if top in foo/bar/box1 is a symbolic link to foo/bar/box2, ".." might take you from /foo/bar/box1/top to foo/bar instead of foo/bar/box1, I remember having encountered such behaviour, I think it was on Solaris).
but how do I compute that in general?)
Ignoring links and the problems they cause for this task and assuming a common root for both paths, import System.FilePath dropCommonPrefix :: Eq a => [a] -> [a] -> ([a],[a]) dropCommonPrefix xxs@(x:xs) yys@(y:ys) | x == y = dropCommonPrefix xs ys dropCommonPrefix xs ys = (xs,ys) shortRelativePath :: FilePath -> FilePath -> FilePath shortRelativePath from to = case dropCommonPrefix (splitDirectories from) (splitDirectories to) of (stuff, path) -> joinPath (map (const "..") stuff ++ path) you might want to normalise and/or canonicalise the paths before, a ".." in `stuff' would screw up the results (and generally, a "baz/.." in either path could be shortened [beware of links, of course]).
participants (2)
-
Andrew Coppin
-
Daniel Fischer