makeRelative

Ian Lynagh ian at well-typed.com
Wed Sep 26 16:47:10 CEST 2012


On Wed, Sep 26, 2012 at 03:30:50PM +0100, Jon Fairbairn wrote:
> 
> I have an application where I want to use relative paths in
> symlinks (so that rsyncing to a different machine with a
> different root directory produces something with the same
> effect).
> 
> So I want
> 
> makeRelative "/var/www/this_server/foo/bar/" "/var/www/this_server/bob"
> 
> to return "../../bob" (which would then be used to create a
> symlink) so that if I copy the tree below /var/www/this_server
> to /var/www/that_server (perhaps on a different machine, but
> copying the symlinks without rewriting them), the symlinks point
> to the same files.
> 
> On posix at least, this would permit isRelative (makeRelative a
> b) always to be True, which is a pleasant property for it to
> have.
> 
> Is there any reason that System.FilePath.Posix.makeRelative should not
> do this? I don’t know enough about non-posix filesystems to know
> whether it even makes sense elsewhere.

Coincidentally, I needed this yesterday, was also surprised to find it
missing, and wrote:

    makeRelativeTo :: FilePath -> FilePath -> FilePath
    this `makeRelativeTo` that = directory </> thisFilename
        where (thisDirectory, thisFilename) = splitFileName this
              thatDirectory = dropFileName that
              directory = joinPath $ f (splitPath thisDirectory)
                                       (splitPath thatDirectory)

              f (x : xs) (y : ys)
               | x == y = f xs ys
              f xs ys = replicate (length ys) ".." ++ xs

(in my case, I know that both paths are absolute).

One thing I wasn't sure of is what to do about different drives on
Windows. Perhaps it would actually need to return a Maybe FilePath?


Thanks
Ian




More information about the Libraries mailing list