hpath-0.6.0: Support for well-typed paths

Copyright© 2016 Julian Ospald
LicenseBSD3
MaintainerJulian Ospald <hasufell@posteo.de>
Stabilityexperimental
Portabilityportable
Safe HaskellSafe
LanguageHaskell2010

System.Posix.FilePath

Contents

Description

The equivalent of System.FilePath on raw (byte string) file paths.

Not all functions of System.FilePath are implemented yet. Feel free to contribute!

Synopsis

Separators

pathSeparator :: Word8 Source

Path separator character

isPathSeparator :: Word8 -> Bool Source

Check if a character is the path separator

\n ->  (_chr n == '/') == isPathSeparator n

searchPathSeparator :: Word8 Source

Search path separator

isSearchPathSeparator :: Word8 -> Bool Source

Check if a character is the search path separator

\n -> (_chr n == ':') == isSearchPathSeparator n

extSeparator :: Word8 Source

File extension separator

isExtSeparator :: Word8 -> Bool Source

Check if a character is the file extension separator

\n -> (_chr n == '.') == isExtSeparator n

File extensions

splitExtension :: RawFilePath -> (RawFilePath, ByteString) Source

Split a RawFilePath into a path+filename and extension

>>> splitExtension "file.exe"
("file",".exe")
>>> splitExtension "file"
("file","")
>>> splitExtension "/path/file.tar.gz"
("/path/file.tar",".gz")
\path -> uncurry (BS.append) (splitExtension path) == path

takeExtension :: RawFilePath -> ByteString Source

Get the final extension from a RawFilePath

>>> takeExtension "file.exe"
".exe"
>>> takeExtension "file"
""
>>> takeExtension "/path/file.tar.gz"
".gz"

replaceExtension :: RawFilePath -> ByteString -> RawFilePath Source

Change a file's extension

\path -> let ext = takeExtension path in replaceExtension path ext == path

dropExtension :: RawFilePath -> RawFilePath Source

Drop the final extension from a RawFilePath

>>> dropExtension "file.exe"
"file"
>>> dropExtension "file"
"file"
>>> dropExtension "/path/file.tar.gz"
"/path/file.tar"

addExtension :: RawFilePath -> ByteString -> RawFilePath Source

Add an extension to a RawFilePath

>>> addExtension "file" ".exe"
"file.exe"
>>> addExtension "file.tar" ".gz"
"file.tar.gz"
>>> addExtension "/path/" ".ext"
"/path/.ext"

hasExtension :: RawFilePath -> Bool Source

Check if a RawFilePath has an extension

>>> hasExtension "file"
False
>>> hasExtension "file.tar"
True
>>> hasExtension "/path.part1/"
False

splitExtensions :: RawFilePath -> (RawFilePath, ByteString) Source

Split a RawFilePath on the first extension

>>> splitExtensions "/path/file.tar.gz"
("/path/file",".tar.gz")
\path -> uncurry addExtension (splitExtensions path) == path

dropExtensions :: RawFilePath -> RawFilePath Source

Remove all extensions from a RawFilePath

>>> dropExtensions "/path/file.tar.gz"
"/path/file"

takeExtensions :: RawFilePath -> ByteString Source

Take all extensions from a RawFilePath

>>> takeExtensions "/path/file.tar.gz"
".tar.gz"

Filenames/Directory names

splitFileName :: RawFilePath -> (RawFilePath, RawFilePath) Source

Split a RawFilePath into (path,file). combine is the inverse

>>> splitFileName "path/file.txt"
("path/","file.txt")
>>> splitFileName "path/"
("path/","")
>>> splitFileName "file.txt"
("./","file.txt")
\path -> uncurry combine (splitFileName path) == path || fst (splitFileName path) == "./"

takeFileName :: RawFilePath -> RawFilePath Source

Get the file name

>>> takeFileName "path/file.txt"
"file.txt"
>>> takeFileName "path/"
""

replaceFileName :: RawFilePath -> ByteString -> RawFilePath Source

Change the file name

\path -> replaceFileName path (takeFileName path) == path

dropFileName :: RawFilePath -> RawFilePath Source

Drop the file name

>>> dropFileName "path/file.txt"
"path/"
>>> dropFileName "file.txt"
"./"

takeBaseName :: RawFilePath -> ByteString Source

Get the file name, without a trailing extension

>>> takeBaseName "path/file.tar.gz"
"file.tar"
>>> takeBaseName ""
""

replaceBaseName :: RawFilePath -> ByteString -> RawFilePath Source

Change the base name

>>> replaceBaseName "path/file.tar.gz" "bob"
"path/bob.gz"
\path -> replaceBaseName path (takeBaseName path) == path

takeDirectory :: RawFilePath -> RawFilePath Source

Get the directory, moving up one level if it's already a directory

>>> takeDirectory "path/file.txt"
"path"
>>> takeDirectory "file"
"."
>>> takeDirectory "/path/to/"
"/path/to"
>>> takeDirectory "/path/to"
"/path"

replaceDirectory :: RawFilePath -> ByteString -> RawFilePath Source

Change the directory component of a RawFilePath

\path -> replaceDirectory path (takeDirectory path) `equalFilePath` path || takeDirectory path == "."

Path combinators and splitters

combine :: RawFilePath -> RawFilePath -> RawFilePath Source

Join two paths together

>>> combine "/" "file"
"/file"
>>> combine "/path/to" "file"
"/path/to/file"
>>> combine "file" "/absolute/path"
"/absolute/path"

(</>) :: RawFilePath -> RawFilePath -> RawFilePath Source

Operator version of combine

splitPath :: RawFilePath -> [RawFilePath] Source

Split a path into a list of components:

>>> splitPath "/path/to/file.txt"
["/","path/","to/","file.txt"]
\path -> BS.concat (splitPath path) == path

joinPath :: [RawFilePath] -> RawFilePath Source

Join a split path back together

\path -> joinPath (splitPath path) == path
>>> joinPath ["path","to","file.txt"]
"path/to/file.txt"

splitDirectories :: RawFilePath -> [RawFilePath] Source

Like splitPath, but without trailing slashes

>>> splitDirectories "/path/to/file.txt"
["/","path","to","file.txt"]
>>> splitDirectories ""
[]

Path conversions

normalise :: RawFilePath -> RawFilePath Source

Normalise a file.

>>> normalise "/file/\\test////"
"/file/\\test/"
>>> normalise "/file/./test"
"/file/test"
>>> normalise "/test/file/../bob/fred/"
"/test/file/../bob/fred/"
>>> normalise "../bob/fred/"
"../bob/fred/"
>>> normalise "./bob/fred/"
"bob/fred/"
>>> normalise "./bob////.fred/./...///./..///#."
"bob/.fred/.../../#."
>>> normalise "."
"."
>>> normalise "./"
"./"
>>> normalise "./."
"./"
>>> normalise "/./"
"/"
>>> normalise "/"
"/"
>>> normalise "bob/fred/."
"bob/fred/"
>>> normalise "//home"
"/home"

Trailing path separator

hasTrailingPathSeparator :: RawFilePath -> Bool Source

Check if the last character of a RawFilePath is /.

>>> hasTrailingPathSeparator "/path/"
True
>>> hasTrailingPathSeparator "/"
True
>>> hasTrailingPathSeparator "/path"
False

addTrailingPathSeparator :: RawFilePath -> RawFilePath Source

Add a trailing path separator.

>>> addTrailingPathSeparator "/path"
"/path/"
>>> addTrailingPathSeparator "/path/"
"/path/"
>>> addTrailingPathSeparator "/"
"/"

dropTrailingPathSeparator :: RawFilePath -> RawFilePath Source

Remove a trailing path separator

>>> dropTrailingPathSeparator "/path/"
"/path"
>>> dropTrailingPathSeparator "/path////"
"/path"
>>> dropTrailingPathSeparator "/"
"/"
>>> dropTrailingPathSeparator "//"
"/"

Queries

isRelative :: RawFilePath -> Bool Source

Check if a path is relative

\path -> isRelative path /= isAbsolute path

isAbsolute :: RawFilePath -> Bool Source

Check if a path is absolute

>>> isAbsolute "/path"
True
>>> isAbsolute "path"
False
>>> isAbsolute ""
False

isValid :: RawFilePath -> Bool Source

Is a FilePath valid, i.e. could you create a file like it?

>>> isValid ""
False
>>> isValid "\0"
False
>>> isValid "/random_ path:*"
True

isFileName :: ByteString -> Bool Source

Is the given filename a valid filename?

>>> isFileName "lal"
True
>>> isFileName "."
True
>>> isFileName ".."
True
>>> isFileName ""
False
>>> isFileName "\0"
False
>>> isFileName "/random_ path:*"
False

hasParentDir :: ByteString -> Bool Source

Helper function: check if the filepath has any parent directories in it.

>>> hasParentDir "/.."
True
>>> hasParentDir "foo/bar/.."
True
>>> hasParentDir "foo/../bar/."
True
>>> hasParentDir "foo/bar"
False
>>> hasParentDir "foo"
False
>>> hasParentDir ""
False
>>> hasParentDir ".."
False

equalFilePath :: RawFilePath -> RawFilePath -> Bool Source

Equality of two filepaths. The filepaths are normalised and trailing path separators are dropped.

>>> equalFilePath "foo" "foo"
True
>>> equalFilePath "foo" "foo/"
True
>>> equalFilePath "foo" "./foo"
True
>>> equalFilePath "foo" "/foo"
False
>>> equalFilePath "foo" "FOO"
False
>>> equalFilePath "foo" "../foo"
False
\p -> equalFilePath p p

hiddenFile :: RawFilePath -> Bool Source

Whether the file is a hidden file.

>>> hiddenFile ".foo"
True
>>> hiddenFile "..foo.bar"
True
>>> hiddenFile "..."
True
>>> hiddenFile "dod"
False
>>> hiddenFile "dod.bar"
False

Type conversion

fpToString :: ByteString -> String Source

Uses UTF-8 decoding to convert the bytestring into a String.

userStringToFP :: String -> ByteString Source

Uses UTF-8 encoding to convert a user provided String into a ByteString, which represents a filepath.