- The main filepath (& dirpath) abstract type
- Phantom Types
- Type Synonyms
- Path to String conversion
- Constants
- Unchecked Construction Functions
- Checked Construction Functions
- Basic Manipulation Functions
- Auxillary Manipulation Functions
- Path Predicates
- Separators
- Flexible Manipulation Functions
- System.Directory replacements
This module provides type-safe access to filepath manipulations.
It is designed to be imported instead of System.FilePath
and
System.Directory
. (It is intended to provide versions of
functions from those modules which have equivalent functionality
but are more typesafe).
The heart of this module is the Path ar fd
abstract type which
represents file and directory paths. The idea is that there are
two phantom type parameters - the first should be Abs
or Rel
,
and the second File
or Dir
. A number of type synonyms are
provided for common types:
type AbsFile = Path Abs File type RelFile = Path Rel File type AbsDir = Path Abs Dir type RelDir = Path Rel Dir type RelPath fd = Path Rel fd type DirPath ar = Path ar Dir
The type of the combine
(aka </>
) function gives the idea:
(</>) :: DirPath ar -> RelPath fd -> Path ar fd
Together this enables us to give more meaningful types to a lot of the functions, and (hopefully) catch a bunch more errors at compile time.
The basic API (and properties satisfied) are heavily influenced
by Neil Mitchell's System.FilePath
module.
WARNING --- THE API IS NOT YET STABLE --- WARNING
Ben Moseley - (c) Jan 2009
- data Path ar fd
- data Abs
- data Rel
- data File
- data Dir
- type AbsFile = Path Abs File
- type RelFile = Path Rel File
- type AbsDir = Path Abs Dir
- type RelDir = Path Rel Dir
- type AbsPath fd = Path Abs fd
- type RelPath fd = Path Rel fd
- type FilePath ar = Path ar File
- type DirPath ar = Path ar Dir
- getPathString :: AbsRelClass ar => Path ar fd -> String
- rootDir :: AbsDir
- currentDir :: RelDir
- mkPath :: String -> Path ar fd
- mkRelFile :: String -> RelFile
- mkRelDir :: String -> RelDir
- mkAbsFile :: String -> AbsFile
- mkAbsDir :: String -> AbsDir
- mkRelPath :: String -> RelPath fd
- mkAbsPath :: String -> AbsPath fd
- mkFile :: String -> FilePath ar
- mkDir :: String -> DirPath ar
- mkPathAbsOrRel :: String -> Either (AbsPath fd) (RelPath fd)
- mkPathFileOrDir :: AbsRelClass ar => String -> IO (Maybe (Either (FilePath ar) (DirPath ar)))
- (</>) :: DirPath ar -> RelPath fd -> Path ar fd
- (<.>) :: FilePath ar -> String -> FilePath ar
- addExtension :: FilePath ar -> String -> FilePath ar
- combine :: DirPath ar -> RelPath fd -> Path ar fd
- dropExtension :: FilePath ar -> FilePath ar
- dropExtensions :: FilePath ar -> FilePath ar
- dropFileName :: Path ar fd -> DirPath ar
- replaceExtension :: FilePath ar -> String -> FilePath ar
- replaceBaseName :: Path ar fd -> String -> Path ar fd
- replaceDirectory :: Path ar1 fd -> DirPath ar2 -> Path ar2 fd
- replaceFileName :: Path ar fd -> String -> Path ar fd
- splitExtension :: FilePath ar -> (FilePath ar, String)
- splitExtensions :: FilePath ar -> (FilePath ar, String)
- splitFileName :: Path ar fd -> (DirPath ar, RelPath fd)
- takeBaseName :: Path ar fd -> RelPath fd
- takeDirectory :: Path ar fd -> DirPath ar
- takeExtension :: FilePath ar -> String
- takeExtensions :: FilePath ar -> String
- takeFileName :: Path ar fd -> RelPath fd
- equalFilePath :: String -> String -> Bool
- joinPath :: [String] -> Path ar fd
- normalise :: Path ar fd -> Path ar fd
- splitDirectories :: Path ar fd -> [String]
- splitPath :: Path ar fd -> [String]
- makeRelative :: AbsDir -> AbsPath fd -> RelPath fd
- isAbsolute :: AbsRelClass ar => Path ar fd -> Bool
- isAbsoluteString :: String -> Bool
- isRelative :: AbsRelClass ar => Path ar fd -> Bool
- isRelativeString :: String -> Bool
- hasExtension :: FilePath ar -> Bool
- addTrailingPathSeparator :: String -> String
- dropTrailingPathSeparator :: String -> String
- extSeparator :: Char
- hasTrailingPathSeparator :: String -> Bool
- pathSeparator :: Char
- pathSeparators :: [Char]
- searchPathSeparator :: Char
- isExtSeparator :: Char -> Bool
- isPathSeparator :: Char -> Bool
- isSearchPathSeparator :: Char -> Bool
- addFileOrDirExtension :: Path ar fd -> String -> Path ar fd
- dropFileOrDirExtension :: Path ar fd -> Path ar fd
- dropFileOrDirExtensions :: Path ar fd -> Path ar fd
- splitFileOrDirExtension :: Path ar fd -> (Path ar fd, String)
- splitFileOrDirExtensions :: Path ar fd -> (Path ar fd, String)
- takeFileOrDirExtension :: Path ar fd -> String
- takeFileOrDirExtensions :: Path ar fd -> String
- getDirectoryContents :: AbsRelClass ar => DirPath ar -> IO ([AbsDir], [AbsFile])
- absDirectoryContents :: AbsRelClass ar => DirPath ar -> IO ([AbsDir], [AbsFile])
- relDirectoryContents :: AbsRelClass ar => DirPath ar -> IO ([RelDir], [RelFile])
The main filepath (& dirpath) abstract type
This is the main filepath abstract datatype
Phantom Types
Type Synonyms
Path to String conversion
getPathString :: AbsRelClass ar => Path ar fd -> StringSource
Constants
Unchecked Construction Functions
Checked Construction Functions
mkPathAbsOrRel :: String -> Either (AbsPath fd) (RelPath fd)Source
Examines the supplied string and constructs an absolute or relative path as appropriate.
Basic Manipulation Functions
(</>) :: DirPath ar -> RelPath fd -> Path ar fdSource
Join an (absolute or relative) directory path with a relative (file or directory) path to form a new path.
(<.>) :: FilePath ar -> String -> FilePath arSource
We only allow files (and not directories) to have extensions added
by this function. This is because it's the vastly common case and
an attempt to add one to a directory will - more often than not -
represent an error.
We don't however want to prevent the corresponding operation on
directories, and so we provide a function that is more flexible:
addFileOrDirExtension
.
addExtension :: FilePath ar -> String -> FilePath arSource
Add an extension, even if there is already one there.
E.g. addExtension "foo.txt" "bat" -> "foo.txt.bat"
.
> addExtension (mkFile "file.txt") "bib" == (mkFile "file.txt.bib") > addExtension (mkFile "file.") ".bib" == (mkFile "file..bib") > addExtension (mkFile "file") ".bib" == (mkFile "file.bib") > takeFileName (addExtension (mkFile "") "ext") == mkFile ".ext" Windows: addExtension "\\\\share" ".txt" == "\\\\share\\.txt"
combine :: DirPath ar -> RelPath fd -> Path ar fdSource
Join an (absolute or relative) directory path with a relative (file or directory) path to form a new path.
dropExtension :: FilePath ar -> FilePath arSource
Remove last extension, and the "." preceding it.
> dropExtension x == fst (splitExtension x)
dropExtensions :: FilePath ar -> FilePath arSource
Drop all extensions
> not $ hasExtension (dropExtensions x)
dropFileName :: Path ar fd -> DirPath arSource
replaceExtension :: FilePath ar -> String -> FilePath arSource
Set the extension of a file, overwriting one if already present.
> replaceExtension (mkFile "file.txt") ".bob" == (mkFile "file.bob") > replaceExtension (mkFile "file.txt") "bob" == (mkFile "file.bob") > replaceExtension (mkFile "file") ".bob" == (mkFile "file.bob") > replaceExtension (mkFile "file.txt") "" == (mkFile "file") > replaceExtension (mkFile "file.fred.bob") "txt" == (mkFile "file.fred.txt")
replaceBaseName :: Path ar fd -> String -> Path ar fdSource
replaceDirectory :: Path ar1 fd -> DirPath ar2 -> Path ar2 fdSource
replaceFileName :: Path ar fd -> String -> Path ar fdSource
splitExtension :: FilePath ar -> (FilePath ar, String)Source
Split on the extension. addExtension
is the inverse.
> uncurry (<.>) (splitExtension x) == x > uncurry addExtension (splitExtension x) == x > splitExtension (mkFile "file.txt") == (mkFile "file",".txt") > splitExtension (mkFile "file") == (mkFile "file","") > splitExtension (mkFile "file/file.txt") == (mkFile "file/file",".txt") > splitExtension (mkFile "file.txt/boris") == (mkFile "file.txt/boris","") > splitExtension (mkFile "file.txt/boris.ext") == (mkFile "file.txt/boris",".ext") > splitExtension (mkFile "file/path.txt.bob.fred") == (mkFile "file/path.txt.bob",".fred")
splitExtensions :: FilePath ar -> (FilePath ar, String)Source
Split on all extensions
> splitExtensions (mkFile "file.tar.gz") == (mkFile "file",".tar.gz")
splitFileName :: Path ar fd -> (DirPath ar, RelPath fd)Source
takeBaseName :: Path ar fd -> RelPath fdSource
takeDirectory :: Path ar fd -> DirPath arSource
takeExtension :: FilePath ar -> StringSource
Get the extension of a file, returns ""
for no extension, .ext
otherwise.
> takeExtension x == snd (splitExtension x) > takeExtension (addExtension x "ext") == ".ext" > takeExtension (replaceExtension x "ext") == ".ext"
takeExtensions :: FilePath ar -> StringSource
Get all extensions
> takeExtensions (mkFile "file.tar.gz") == ".tar.gz"
takeFileName :: Path ar fd -> RelPath fdSource
Auxillary Manipulation Functions
equalFilePath :: String -> String -> BoolSource
normalise :: Path ar fd -> Path ar fdSource
Currently just transforms:
> normalise (mkFile "/tmp/fred/./jim/./file") == mkFile "/tmp/fred/jim/file"
splitDirectories :: Path ar fd -> [String]Source
makeRelative :: AbsDir -> AbsPath fd -> RelPath fdSource
Path Predicates
isAbsolute :: AbsRelClass ar => Path ar fd -> BoolSource
isAbsoluteString :: String -> BoolSource
isRelative :: AbsRelClass ar => Path ar fd -> BoolSource
Invariant - this should return True iff arg is of type Path Rel _
isRelativeString :: String -> BoolSource
hasExtension :: FilePath ar -> BoolSource
Does the given filename have an extension?
> null (takeExtension x) == not (hasExtension x)
Separators
addTrailingPathSeparator :: String -> StringSource
This is largely for System.FilePath
compatability
dropTrailingPathSeparator :: String -> StringSource
This is largely for System.FilePath
compatability
File extension character
> extSeparator == '.'
hasTrailingPathSeparator :: String -> BoolSource
This is largely for System.FilePath
compatability
The character that separates directories. In the case where more than
one character is possible, pathSeparator
is the 'ideal' one.
Windows: pathSeparator == '\\' Posix: pathSeparator == '/' > isPathSeparator pathSeparator
pathSeparators :: [Char]Source
The list of all possible separators.
Windows: pathSeparators == ['\\', '/'] Posix: pathSeparators == ['/'] > pathSeparator `elem` pathSeparators
searchPathSeparator :: CharSource
The character that is used to separate the entries in the $PATH environment variable.
Windows: searchPathSeparator == ';' Posix: searchPathSeparator == ':'
isExtSeparator :: Char -> BoolSource
Is the character an extension character?
> isExtSeparator a == (a == extSeparator)
isPathSeparator :: Char -> BoolSource
Rather than using (==
, use this. Test if something
is a path separator.
pathSeparator
)
> isPathSeparator a == (a `elem` pathSeparators)
isSearchPathSeparator :: Char -> BoolSource
Is the character a file separator?
> isSearchPathSeparator a == (a == searchPathSeparator)
Flexible Manipulation Functions
addFileOrDirExtension :: Path ar fd -> String -> Path ar fdSource
This is a more flexible variant of addExtension
/ .
which can
work with files or directories
> addFileOrDirExtension (mkFile "/") "x" == (mkFile "/.x")
dropFileOrDirExtension :: Path ar fd -> Path ar fdSource
dropFileOrDirExtensions :: Path ar fd -> Path ar fdSource
splitFileOrDirExtension :: Path ar fd -> (Path ar fd, String)Source
splitFileOrDirExtensions :: Path ar fd -> (Path ar fd, String)Source
takeFileOrDirExtension :: Path ar fd -> StringSource
takeFileOrDirExtensions :: Path ar fd -> StringSource
System.Directory replacements
absDirectoryContents :: AbsRelClass ar => DirPath ar -> IO ([AbsDir], [AbsFile])Source
Retrieve the contents of a directory path (which may be relative) as absolute paths
relDirectoryContents :: AbsRelClass ar => DirPath ar -> IO ([RelDir], [RelFile])Source
Returns paths relative to the supplied (abs or relative) directory path.
eg (for current working directory of /somewhere/cwd/
):
show (relDirectoryContents (mkRelDir "subDir1")) == (["subDir1A","subDir1B"], ["file1A","file1B"])