I want to make a function to expand names of the form ~user
with that user's home directory (usually /home/user/
), including ~root
, which is typically /root/
. I know of the getHomeDirectory
method, to get the current user's home, but I don't know of any function to determine the home directory of a given user.
I have the following function, which replaces a leading ~
in any file path with the user's home directory
-- join path with '/', except at root
-- opposite of breakPath
rejoinPath :: [FilePath] -> FilePath
rejoinPath [] = ""
rejoinPath (p:ps)
| p == "/" = p ++ go ps
| otherwise = go (p:ps)
where
go :: [FilePath] -> FilePath
go [] = ""
go [p] = p
go (p:ps) = p ++ "/" ++ go ps
-- split path on '/', erasing separator except at root
-- opposite of rejoinPath
breakPath :: FilePath -> [FilePath]
breakPath [] = []
breakPath (c:cs)
| c == '/' = "/" : go "" cs
| otherwise = go [c] cs
where
go :: FilePath -> FilePath -> [FilePath]
go z [] = [z]
go z (c:cs)
| c == '/' = z : go "" cs
| otherwise = go (z ++ [c]) cs
expandHome :: FilePath -> IO FilePath
expandHome p = rejoinPath <$> (go $ breakPath p)
where
go [] = pure []
go (p:ps)
| p == "~" = do
home <- getHomeDirectory
pure $ home : ps
| otherwise = pure $ p : ps
My understanding is that the getHomeDirectory
reads from the HOME
environment variable, and that the other home directories would be considerably harder to procure, but not impossible or prohibitively difficult I hope.
I'm only interested in linux systems at the moment; I understand Windows and Mac have entirely different styles.
It looks like this is available in the unix package using getUserEntryForName and then the homeDirectory
field of UserEntry
.
import System.Posix.User
main :: IO ()
main = do entry <- getUserEntryForName "djf"
putStrLn (homeDirectory entry)