-- | This module provides type-safe access to directory manipulations. -- -- It is designed to be imported instead of "System.Directory". -- (It is intended to provide versions of functions from that -- module which have equivalent functionality but are more -- typesafe). "System.Path" is a companion module providing -- a type-safe alternative to "System.FilePath". -- -- You will typically want to import as follows: -- -- > import Prelude hiding (FilePath) -- > import System.Path -- > import System.Path.Directory -- > import System.Path.IO -- -- -- Ben Moseley - (c) 2009 -- module System.Path.Directory ( -- * Actions on directories createDirectory, createDirectoryIfMissing, removeDirectory, removeDirectoryRecursive, renameDirectory, getDirectoryContents, absDirectoryContents, relDirectoryContents, filesInDir, dirsInDir, getCurrentDirectory, setCurrentDirectory, -- * Pre-defined directories getHomeDirectory, getAppUserDataDirectory, getUserDocumentsDirectory, getTemporaryDirectory, -- * Actions on files removeFile, renameFile, copyFile, canonicalizePath, makeRelativeToCurrentDirectory, findExecutable, -- * Existence tests doesFileExist, doesDirectoryExist, -- * Permissions Permissions, getPermissions, setPermissions, -- * Timestamps getModificationTime ) where import qualified System.Path.Internal.PartClass as Class import qualified System.Path as Path import System.Path ( Path, path, AbsPath, AbsDir, AbsFile, RelPath, RelDir, RelFile, DirPath, FilePath, absDir, (), ) import System.Path.ModificationTime (convertTime) import Data.Time (UTCTime) import qualified System.Directory as SD import System.Directory (Permissions) import Control.Applicative ((<$>)) import Data.List (partition) import Data.Tuple.HT (mapPair) import Prelude hiding (FilePath) ------------------------------------------------------------------------ -- Actions on directories createDirectory :: Class.AbsRel ar => DirPath ar -> IO () createDirectory = SD.createDirectory . Path.toString createDirectoryIfMissing :: Class.AbsRel ar => Bool -> DirPath ar -> IO () createDirectoryIfMissing flag = SD.createDirectoryIfMissing flag . Path.toString removeDirectory :: Class.AbsRel ar => DirPath ar -> IO () removeDirectory = SD.removeDirectory . Path.toString removeDirectoryRecursive :: Class.AbsRel ar => DirPath ar -> IO () removeDirectoryRecursive = SD.removeDirectoryRecursive . Path.toString renameDirectory :: (Class.AbsRel ar1, Class.AbsRel ar2) => DirPath ar1 -> DirPath ar2 -> IO () renameDirectory p1 p2 = SD.renameDirectory (Path.toString p1) (Path.toString p2) -- | Retrieve the contents of a directory without any directory prefixes. -- In contrast to 'System.Directory.getDirectoryContents', -- exclude special directories \".\" and \"..\". getDirectoryContents :: Class.AbsRel ar => DirPath ar -> IO [Path.RelFileDir] getDirectoryContents dir = map Path.path <$> plainDirectoryContents dir -- | Retrieve the contents of a directory path (which may be relative) as absolute paths absDirectoryContents :: Class.AbsRel ar => DirPath ar -> IO ([AbsDir], [AbsFile]) absDirectoryContents p = do cd <- absDir <$> SD.getCurrentDirectory let dir = Path.withAbsRel id (cd ) p mapPair (map (dir ), map (dir )) <$> relDirectoryContents dir -- | Returns paths relative /to/ the supplied (abs or relative) directory path. -- eg (for current working directory of @\/somewhere\/cwd\/@): -- -- > show (relDirectoryContents "d/e/f/") == (["subDir1A","subDir1B"], -- > ["file1A","file1B"]) -- relDirectoryContents :: Class.AbsRel ar => DirPath ar -> IO ([RelDir], [RelFile]) relDirectoryContents dir = do filenames <- plainDirectoryContents dir mapPair (map (Path.relDir . fst), map (Path.relFile . fst)) . partition snd . zip filenames <$> mapM (doesDirectoryExist . (dir ) . Path.relPath) filenames plainDirectoryContents :: Class.AbsRel ar => DirPath ar -> IO [String] plainDirectoryContents dir = filter (not . flip elem [".",".."]) <$> SD.getDirectoryContents (Path.toString dir) -- | A convenient alternative to 'relDirectoryContents' if you only want files. filesInDir :: Class.AbsRel ar => DirPath ar -> IO [RelFile] filesInDir dir = snd <$> relDirectoryContents dir -- | A convenient alternative to 'relDirectoryContents' if you only want directories. dirsInDir :: Class.AbsRel ar => DirPath ar -> IO [RelDir] dirsInDir dir = fst <$> relDirectoryContents dir getCurrentDirectory :: IO AbsDir getCurrentDirectory = absDir <$> SD.getCurrentDirectory setCurrentDirectory :: Class.AbsRel ar => DirPath ar -> IO () setCurrentDirectory = SD.setCurrentDirectory . Path.toString ------------------------------------------------------------------------ -- Pre-defined directories getHomeDirectory :: IO AbsDir getHomeDirectory = absDir <$> SD.getHomeDirectory getAppUserDataDirectory :: String -> IO AbsDir getAppUserDataDirectory user = absDir <$> SD.getAppUserDataDirectory user getUserDocumentsDirectory :: IO AbsDir getUserDocumentsDirectory = absDir <$> SD.getUserDocumentsDirectory getTemporaryDirectory :: IO AbsDir getTemporaryDirectory = absDir <$> SD.getTemporaryDirectory ------------------------------------------------------------------------ -- Actions on files removeFile :: Class.AbsRel ar => FilePath ar -> IO () removeFile = SD.removeFile . Path.toString renameFile :: (Class.AbsRel ar1, Class.AbsRel ar2) => FilePath ar1 -> FilePath ar2 -> IO () renameFile p1 p2 = SD.renameFile (Path.toString p1) (Path.toString p2) copyFile :: (Class.AbsRel ar1, Class.AbsRel ar2) => FilePath ar1 -> FilePath ar2 -> IO () copyFile p1 p2 = SD.copyFile (Path.toString p1) (Path.toString p2) canonicalizePath :: (Class.AbsRel ar, Class.FileDir fd) => Path ar fd -> IO (AbsPath fd) canonicalizePath p = path <$> SD.canonicalizePath (Path.toString p) makeRelativeToCurrentDirectory :: (Class.AbsRel ar, Class.FileDir fd) => Path ar fd -> IO (RelPath fd) makeRelativeToCurrentDirectory p = path <$> SD.makeRelativeToCurrentDirectory (Path.toString p) findExecutable :: String -> IO (Maybe AbsFile) findExecutable s = fmap path <$> SD.findExecutable s ------------------------------------------------------------------------ -- Existence tests doesFileExist :: Class.AbsRel ar => FilePath ar -> IO Bool doesFileExist = SD.doesFileExist . Path.toString doesDirectoryExist :: Class.AbsRel ar => DirPath ar -> IO Bool doesDirectoryExist = SD.doesDirectoryExist . Path.toString ------------------------------------------------------------------------ -- Permissions getPermissions :: (Class.AbsRel ar, Class.FileDir fd) => Path ar fd -> IO Permissions getPermissions p = SD.getPermissions (Path.toString p) setPermissions :: (Class.AbsRel ar, Class.FileDir fd) => Path ar fd -> Permissions -> IO () setPermissions p perms = SD.setPermissions (Path.toString p) perms ------------------------------------------------------------------------ -- Timestamps getModificationTime :: (Class.AbsRel ar, Class.FileDir fd) => Path ar fd -> IO UTCTime getModificationTime p = convertTime <$> SD.getModificationTime (Path.toString p)