1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
------------------------------------------------------------------------------
--- Library to support operations related to the program execution path,
--- i.e., environment variable `PATH`.
---
--- @author Michael Hanus
--- @version November 2018
------------------------------------------------------------------------------

module System.Path
  ( dirsInPath, fileInPath, getFileInPath )
 where

import Directory ( doesFileExist, getAbsolutePath )
import FilePath  ( (</>), searchPathSeparator )
import List      ( split )
import System    ( getEnviron )

--- Returns the list of the directories of the environment variable `PATH`.
dirsInPath :: IO [String]
dirsInPath = do
  path <- getEnviron "PATH"
  return $ split (== searchPathSeparator) path

--- Checks whether a file exists in one of the directories
--- of the environment variable `PATH`.
fileInPath :: String -> IO Bool
fileInPath file = do
  dirs <- dirsInPath
  (liftIO (any id)) $ mapIO (doesFileExist . (</> file)) dirs

--- Checks whether a file exists in one of the directories
--- of the environment variable `PATH` and returns its absolute path,
--- otherwise returns `Nothing`.
getFileInPath :: String -> IO (Maybe String)
getFileInPath file = dirsInPath >>= checkPath
 where
  checkPath [] = return Nothing
  checkPath (dir:dirs) = do
    let dirfile = dir </> file
    direx <- doesFileExist dirfile
    if direx then getAbsolutePath dirfile >>= return . Just
             else checkPath dirs

------------------------------------------------------------------------------