FilePath-0.11: Library for manipulating FilePath's in a cross platform way.ContentsIndex
System.FilePath.Version_0_09
Portabilityportable
Stabilitydepreciated
Maintainerhttp://www.cs.york.ac.uk/~ndm/
Contents
The basic functions
Path methods (environment $PATH)
Extension methods
Operations on a filepath, as a list of directories
File name manipulators
Directory operations
Temporary file operations
Description

This is the old interface for System.FilePath - now depreciated. Please use System.FilePath for new programs, and think about converting your old ones over (or email me and I'll send you a patch)

I have used 3 codes to indicate what happened to each method:

  • GONE means the method is entirely removed - with where the best alternative is
  • RENAMED means the method got renamed
  • Nothing means the method remains the same.

A library for FilePath manipulations, designed to be cross platform. This library will select the correct type of FilePath's for the platform the code is running on at runtime. For more details see http://www.cs.york.ac.uk/~ndm/projects/libraries.php

Some short examples:

You are given a C file, you want to figure out the corresponding object (.o) file:

setExtension file "o"

Haskell module Main imports Test, you have the file named main:

[setFileName path_to_main "Test" <.> ext | ext <- ["hs","lhs"] ]

You want to download a file from the web and save it to disk:

do let file = makeValid url
   ensureDirectory (getDirectory file)

You want to compile a Haskell file, but put the hi file under "interface"

getDirectory file </> "interface" </> (getFileName file `setExtension` "hi")

You want to display a filename to the user, as neatly as possible

shortPath file >>= putStrLn

The examples in code format descibed by each function are used to generate tests, and should give clear semantics for the functions.

Synopsis
pathSeparator :: Char
pathSeparators :: [Char]
isPathSeparator :: Char -> Bool
fileSeparator :: Char
isFileSeparator :: Char -> Bool
extSeparator :: Char
isExtSeparator :: Char -> Bool
splitFiles :: String -> [FilePath]
getPath :: IO [FilePath]
splitExtension :: FilePath -> (String, String)
joinExtension :: String -> String -> FilePath
getExtension :: FilePath -> String
setExtension :: FilePath -> String -> FilePath
dropExtension :: FilePath -> FilePath
addExtension :: FilePath -> String -> FilePath
hasExtension :: FilePath -> Bool
(<.>) :: FilePath -> String -> FilePath
splitExtensions :: FilePath -> (FilePath, String)
dropExtensions :: FilePath -> FilePath
getExtensions :: FilePath -> String
splitFileName :: FilePath -> (String, String)
joinFileName :: FilePath -> String -> FilePath
getFileName :: FilePath -> FilePath
setFileName :: FilePath -> String -> FilePath
dropFileName :: FilePath -> FilePath
addFileName :: FilePath -> String -> FilePath
getBaseName :: FilePath -> String
setBaseName :: FilePath -> String -> FilePath
getDirectory :: FilePath -> FilePath
setDirectory :: FilePath -> String -> FilePath
isDirectory :: FilePath -> Bool
combine :: FilePath -> FilePath -> FilePath
(</>) :: FilePath -> FilePath -> FilePath
splitPath :: FilePath -> [FilePath]
joinPath :: [FilePath] -> FilePath
splitDirectories :: FilePath -> [FilePath]
canonicalPath :: FilePath -> IO FilePath
normalise :: FilePath -> FilePath
equalFilePath :: FilePath -> FilePath -> Bool
fullPath :: FilePath -> IO FilePath
fullPathWith :: FilePath -> FilePath -> FilePath
shortPath :: FilePath -> IO FilePath
shortPathWith :: FilePath -> FilePath -> FilePath
isRelative :: FilePath -> Bool
isAbsolute :: FilePath -> Bool
isValid :: FilePath -> Bool
makeValid :: FilePath -> FilePath
getDirectoryList :: FilePath -> IO [String]
ensureDirectory :: FilePath -> IO ()
getTemporaryFile :: String -> IO FilePath
getTemporaryFileNew :: String -> IO (Maybe FilePath)
getTemporaryFileSeed :: Int -> String -> IO FilePath
The basic functions
pathSeparator :: Char

The character that seperates directories. In the case where more than one character is possible, pathSeperator is the ideal one.

 Windows: pathSeparator == '\\'
 Posix:   pathSeparator ==  '/'
 isPathSeparator pathSeparator
pathSeparators :: [Char]

The list of all possible seperators.

 Windows: pathSeparators == ['\\', '/']
 Posix:   pathSeparators == ['/']
 pathSeparator `elem` pathSeparators
isPathSeparator :: Char -> Bool

Rather than using (== pathSeperator), use this. Test if something is a path separator.

 isPathSeparator a == (a `elem` pathSeparators)
fileSeparator :: Char

A list of possible file separators, between the $PATH variable

 Windows: fileSeparator == ';'
 Posix:   fileSeparator == ':'
isFileSeparator :: Char -> Bool

Is the character a file separator?

 isFileSeparator a == (a == fileSeparator)
extSeparator :: Char

File extension character

 extSeparator == '.'
isExtSeparator :: Char -> Bool

Is the character an extension character?

 isExtSeparator a == (a == extSeparator)
Path methods (environment $PATH)
splitFiles :: String -> [FilePath]

Take a string, split it on the fileSeparators character.

 Windows: splitFiles "File1;File2;File3" == ["File1","File2","File3"]
 Posix:   splitFiles "File1:File2:File3" == ["File1","File2","File3"]
getPath :: IO [FilePath]
RENAMED - getSearchPath. Get a list of filepaths in the $PATH.
Extension methods
splitExtension :: FilePath -> (String, String)

Split on the extension.

 uncurry (++) (splitExtension x) == x
 splitExtension "file.txt" == ("file",".txt")
 splitExtension "file" == ("file","")
 splitExtension "file/file.txt" == ("file/file",".txt")
 splitExtension "file.txt/boris" == ("file.txt/boris","")
 splitExtension "file.txt/boris.ext" == ("file.txt/boris",".ext")
 splitExtension "file/path.txt.bob.fred" == ("file/path.txt.bob",".fred")
 splitExtension "file/path.txt/" == ("file/path.txt/","")
joinExtension :: String -> String -> FilePath

RENAMED - addExtension. Join an extension and a filepath.

 uncurry joinExtension (splitExtension x) == x
getExtension :: FilePath -> String

RENAMED - takeExtension. Get the extension of a file, returns "" for no extension, .ext otherwise.

 getExtension x == snd (splitExtension x)
 getExtension (addExtension x "ext") == ".ext"
 getExtension (setExtension x "ext") == ".ext"
setExtension :: FilePath -> String -> FilePath

RENAMED - replaceExtension. Set the extension of a file, overwriting one if already present.

 setExtension "file.txt" ".bob" == "file.bob"
 setExtension "file.txt" "bob" == "file.bob"
 setExtension "file" ".bob" == "file.bob"
 setExtension "file.txt" "" == "file"
 setExtension "file.fred.bob" "txt" == "file.fred.txt"
dropExtension :: FilePath -> FilePath

Remove last extension, and any . following it.

 dropExtension x == fst (splitExtension x)
addExtension :: FilePath -> String -> FilePath

Add an extension, even if there is already one there. E.g. addExtension "foo.txt" "bat" -> "foo.txt.bat".

 addExtension "file.txt" "bib" == "file.txt.bib"
 addExtension "file." ".bib" == "file..bib"
 addExtension "file" ".bib" == "file.bib"
 Windows: addExtension "\\\\share" ".txt" == "\\\\share\\.txt"
hasExtension :: FilePath -> Bool

Does the given filename have an extension?

 null (getExtension x) == not (hasExtension x)
(<.>) :: FilePath -> String -> FilePath
Alias to addExtension, for people who like that sort of thing.
splitExtensions :: FilePath -> (FilePath, String)

Split on all extensions

 splitExtensions "file.tar.gz" == ("file",".tar.gz")
dropExtensions :: FilePath -> FilePath

Drop all extensions

 not $ hasExtension (dropExtensions x)
getExtensions :: FilePath -> String
RENAMED - takeExtensions. Get all extensions
Operations on a filepath, as a list of directories
splitFileName :: FilePath -> (String, String)

Split a filename into directory and file.

 uncurry (++) (splitFileName x) == x
 splitFileName "file/bob.txt" == ("file/", "bob.txt")
 splitFileName "file/" == ("file/", "")
 splitFileName "bob" == ("", "bob")
 Posix:   splitFileName "/" == ("/","")
 Windows: splitFileName "c:" == ("c:","")
joinFileName :: FilePath -> String -> FilePath

RENAMED - addFileName. Join a directory and filename.

 uncurry joinFileName (splitFileName x) == x
getFileName :: FilePath -> FilePath

RENAMED - takeFileName. Get the file name.

 getFileName "test/" == ""
 getFileName x == snd (splitFileName x)
 getFileName (setFileName x "fred") == "fred"
 getFileName (addFileName x "fred") == "fred"
setFileName :: FilePath -> String -> FilePath

RENAMED - replaceFileName. Set the filename.

 setFileName x (getFileName x) == x
dropFileName :: FilePath -> FilePath

Drop the filename.

 dropFileName x == fst (splitFileName x)
addFileName :: FilePath -> String -> FilePath

Add a filename onto the end of a path.

 addFileName (getDirectory x) (getFileName x) `equalFilePath` x
getBaseName :: FilePath -> String

RENAMED - takeBaseName. Get the base name, without an extension or path.

 getBaseName "file/test.txt" == "test"
 getBaseName "dave.ext" == "dave"
setBaseName :: FilePath -> String -> FilePath

RENAMED - replaceBaseName. Set the base name.

 setBaseName "file/test.txt" "bob" == "file/bob.txt"
 setBaseName "fred" "bill" == "bill"
getDirectory :: FilePath -> FilePath

RENAMED - takeDirectory. Get the directory name, move up one level.

 Posix:    getDirectory "/foo/bar/baz" == "/foo/bar"
 Posix:    getDirectory "/foo/bar/baz/" == "/foo/bar/baz"
setDirectory :: FilePath -> String -> FilePath

RENAMED - replaceDirectory. Set the directory, keeping the filename the same.

 setDirectory x (getDirectory x) `equalFilePath` x
isDirectory :: FilePath -> Bool

Is an item either a directory or the last character a path separator? This does not query the file system.

 isDirectory "test" == False
 isDirectory "test/" == True
combine :: FilePath -> FilePath -> FilePath

Combine two paths, if the right path isAbsolute, then it returns the second.

 Posix:   combine "/" "test" == "/test"
 Posix:   combine "home" "bob" == "home/bob"
 Windows: combine "home" "bob" == "home\\bob"
(</>) :: FilePath -> FilePath -> FilePath
A nice alias for combine. E.g. "home" </> "bob" -> "home/bob" on Unix or "home\bob" on Windows.
splitPath :: FilePath -> [FilePath]

Split a path by the directory seperator.

 concat (splitPath x) == x
 splitPath "test//item/" == ["test//","item/"]
 splitPath "test/item/file" == ["test/","item/","file"]
 splitPath "" == []
 Windows: splitPath "c:\\test\\path" == ["c:\\","test\\","path"]
 Posix:   splitPath "/file/test" == ["/","file/","test"]
joinPath :: [FilePath] -> FilePath

Join path elements back together.

 joinPath (splitPath x) == x
splitDirectories :: FilePath -> [FilePath]

Just as splitPath, but don't add the trailing slashes to each element.

 splitDirectories "test/file" == ["test","file"]
 splitDirectories "/test/file" == ["/","test","file"]
 joinPath (splitDirectories x) `equalFilePath` x
 splitDirectories "" == []
File name manipulators
canonicalPath :: FilePath -> IO FilePath
GONE - see System.Directory.canonicalizePath. Find the canoncial path, if the file exists then the case will be correct on Windows, if the file is a directory it will have a trailing slash appended on all operating systems.
normalise :: FilePath -> FilePath

Normalise a file

  • // outside of the drive can be made blank
  • / -> pathSeparator
  • ./ -> ""
  • item/../ -> ""
 Posix:   normalise "/file/\\test////" == "/file/\\test/"
 Posix:   normalise "/file/./test" == "/file/test"
 Posix:   normalise "/test/file/../bob/fred/" == "/test/bob/fred/"
 Posix:   normalise "../bob/fred/" == "../bob/fred/"
 Posix:   normalise "./bob/fred/" == "bob/fred/"
 Windows: normalise "c:\\file/bob\\" == "C:\\file\\bob\\"
 Windows: normalise "\\\\server\\test" == "\\\\server\\test"
 Windows: normalise "c:/file" == "C:\\file"
equalFilePath :: FilePath -> FilePath -> Bool
Equality of two FilePaths. If you call fullPath first this has a much better chance of working. Note that this doesn't follow symlinks or DOSNAM~1s.
fullPath :: FilePath -> IO FilePath
GONE - see System.Directory.canonicalizePath. fullPathWith the current directory.
fullPathWith :: FilePath -> FilePath -> FilePath

GONE - see System.Directory.canonicalizePath. Expand out a filename to its full name, with the a directory factored in.

 Posix:   fullPathWith "/file/test/" "/bob/dave" == "/bob/dave"
 Posix:   fullPathWith "/file/test/" "bob" == "/file/test/bob"
 Posix:   fullPathWith "/file/test/" "../bob" == "/file/bob"
shortPath :: FilePath -> IO FilePath
shortPathWith the current directory.
shortPathWith :: FilePath -> FilePath -> FilePath

Contract a filename, based on a relative path.

 Posix:   shortPathWith "/home/" "/home/bob/foo/bar" == "bob/foo/bar"
 Posix:   shortPathWith "/fred" "bob" == "bob"
 Posix:   shortPathWith "/file/test" "/file/test/fred" == "fred"
 Posix:   shortPathWith "/file/test" "/file/test/fred/" == "fred/"
 Posix:   shortPathWith "/fred/dave" "/fred/bill" == "../bill"
isRelative :: FilePath -> Bool

Is a path relative, or is it fixed to the root?

 Windows: isRelative "path\\test" == True
 Windows: isRelative "c:\\test" == False
 Posix:   isRelative "test/path" == True
 Posix:   isRelative "/test" == False
isAbsolute :: FilePath -> Bool
not . isRelative
 isAbsolute x == not (isRelative x)
isValid :: FilePath -> Bool

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

 Posix:   isValid "/random_ path:*" == True
 Posix:   isValid x == True
 Windows: isValid "c:\\test" == True
 Windows: isValid "c:\\test:of_test" == False
 Windows: isValid "test*" == False
 Windows: isValid "c:\\test\\nul" == False
 Windows: isValid "c:\\test\\prn.txt" == False
 Windows: isValid "c:\\nul\\file" == False
makeValid :: FilePath -> FilePath

Take a FilePath and make it valid; does not change already valid FilePaths.

 isValid (makeValid x)
 if isValid x then makeValid x == x else True
 Windows: makeValid "c:\\test:of_test" == "c:\\test_of_test"
 Windows: makeValid "test*" == "test_"
 Windows: makeValid "c:\\test\\nul" == "c:\\test\\nul_"
 Windows: makeValid "c:\\test\\prn.txt" == "c:\\test\\prn_.txt"
 Windows: makeValid "c:\\test/prn.txt" == "c:\\test/prn_.txt"
 Windows: makeValid "c:\\nul\\file" == "c:\\nul_\\file"
Directory operations
getDirectoryList :: FilePath -> IO [String]
GONE - I miss this :(. Get a list of all the directories within this directory.
ensureDirectory :: FilePath -> IO ()
GONE see System.Directory.createDirectoryIfMissing. Makes a directory and all its parents (mkdir -p). For example ensureDirectory "./One/Two/Three" would create the directory "Two" and "Three" if "." and "One" already existed.
Temporary file operations
getTemporaryFile :: String -> IO FilePath
GONE - see System.IO.openTempFile. Get a temporary file name.
getTemporaryFileNew :: String -> IO (Maybe FilePath)
GONE - see System.IO.openTempFile. Get a temporary file name which does not exist. Beware of race conditions, the file may be created after this function returns. Nothing may be returned if a new item is not found in 100 tries.
getTemporaryFileSeed :: Int -> String -> IO FilePath
GONE - see System.IO.openTempFile. Get a temporary file name, using a specified number as a seed.
Produced by Haddock version 0.8