| ||||||||
| ||||||||
| ||||||||
Description | ||||||||
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: replaceExtension file "o" Haskell module Main imports Test, you have the file named main: [replaceFileName 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 System.IO.createDirectoryIfMissing True (takeDirectory file) You want to compile a Haskell file, but put the hi file under "interface" takeDirectory file </> "interface" </> (takeFileName file `replaceExtension` "hi") You want to display a filename to the user, as neatly as possible makeRelativeToCurrentDirectory 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 | ||||||||
Separator predicates | ||||||||
pathSeparator :: Char | ||||||||
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] | ||||||||
The list of all possible separators. Windows: pathSeparators == ['\\', '/'] Posix: pathSeparators == ['/'] pathSeparator `elem` pathSeparators | ||||||||
isPathSeparator :: Char -> Bool | ||||||||
Rather than using (== pathSeparator), use this. Test if something is a path separator. isPathSeparator a == (a `elem` pathSeparators) | ||||||||
searchPathSeparator :: Char | ||||||||
A list of possible file separators, between the $PATH variable Windows: searchPathSeparator == ';' Posix: searchPathSeparator == ':' | ||||||||
isSearchPathSeparator :: Char -> Bool | ||||||||
Is the character a file separator? isSearchPathSeparator a == (a == searchPathSeparator) | ||||||||
extSeparator :: Char | ||||||||
File extension character extSeparator == '.' | ||||||||
isExtSeparator :: Char -> Bool | ||||||||
Is the character an extension character? isExtSeparator a == (a == extSeparator) | ||||||||
Path methods (environment $PATH) | ||||||||
splitSearchPath :: String -> [FilePath] | ||||||||
Take a string, split it on the searchPathSeparator character. Windows: splitSearchPath "File1;File2;File3" == ["File1","File2","File3"] Posix: splitSearchPath "File1:File2:File3" == ["File1","File2","File3"] | ||||||||
getSearchPath :: IO [FilePath] | ||||||||
Get a list of filepaths in the $PATH. | ||||||||
Extension methods | ||||||||
splitExtension :: FilePath -> (String, String) | ||||||||
Split on the extension. addExtension is the inverse. uncurry (++) (splitExtension x) == x uncurry addExtension (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/","") | ||||||||
takeExtension :: FilePath -> String | ||||||||
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" | ||||||||
replaceExtension :: FilePath -> String -> FilePath | ||||||||
Set the extension of a file, overwriting one if already present. replaceExtension "file.txt" ".bob" == "file.bob" replaceExtension "file.txt" "bob" == "file.bob" replaceExtension "file" ".bob" == "file.bob" replaceExtension "file.txt" "" == "file" replaceExtension "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 (takeExtension 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) | ||||||||
takeExtensions :: FilePath -> String | ||||||||
Get all extensions | ||||||||
Operations on a filepath, as a list of directories | ||||||||
splitFileName :: FilePath -> (String, String) | ||||||||
Split a filename into directory and file. combine is the inverse. uncurry (++) (splitFileName x) == x uncurry combine (splitFileName x) == x splitFileName "file/bob.txt" == ("file/", "bob.txt") splitFileName "file/" == ("file/", "") splitFileName "bob" == ("", "bob") Posix: splitFileName "/" == ("/","") Windows: splitFileName "c:" == ("c:","") | ||||||||
takeFileName :: FilePath -> FilePath | ||||||||
Get the file name. takeFileName "test/" == "" takeFileName x == snd (splitFileName x) takeFileName (replaceFileName x "fred") == "fred" takeFileName (combine x "fred") == "fred" isRelative (takeFileName x) | ||||||||
replaceFileName :: FilePath -> String -> FilePath | ||||||||
Set the filename. replaceFileName x (takeFileName x) == x | ||||||||
dropFileName :: FilePath -> FilePath | ||||||||
Drop the filename. dropFileName x == fst (splitFileName x) | ||||||||
takeBaseName :: FilePath -> String | ||||||||
Get the base name, without an extension or path. takeBaseName "file/test.txt" == "test" takeBaseName "dave.ext" == "dave" | ||||||||
replaceBaseName :: FilePath -> String -> FilePath | ||||||||
Set the base name. replaceBaseName "file/test.txt" "bob" == "file/bob.txt" replaceBaseName "fred" "bill" == "bill" replaceBaseName "/dave/fred/bob.gz.tar" "new" == "/dave/fred/new.tar" replaceBaseName x (takeBaseName x) == x | ||||||||
takeDirectory :: FilePath -> FilePath | ||||||||
Get the directory name, move up one level. Posix: takeDirectory "/foo/bar/baz" == "/foo/bar" Posix: takeDirectory "/foo/bar/baz/" == "/foo/bar/baz" | ||||||||
replaceDirectory :: FilePath -> String -> FilePath | ||||||||
Set the directory, keeping the filename the same. replaceDirectory x (takeDirectory 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 | ||||||||
isFile :: FilePath -> Bool | ||||||||
Is an item a file, does not query the file system. isDirectory x == not (isFile x) | ||||||||
asDirectory :: FilePath -> FilePath | ||||||||
Make something look like a directory isDirectory (asDirectory x) if isDirectory x then asDirectory x == x else True Posix: asDirectory "test/rest" == "test/rest/" | ||||||||
asFile :: FilePath -> FilePath | ||||||||
Make something look like a file asFile "file/test/" == "file/test" not (isDirectory (asFile x)) || isDrive x Posix: asFile "/" == "/" | ||||||||
combine :: FilePath -> FilePath -> FilePath | ||||||||
Combine two paths, if the second path isAbsolute, then it returns the second. combine (takeDirectory x) (takeFileName x) `equalFilePath` x Posix: combine "/" "test" == "/test" Posix: combine "home" "bob" == "home/bob" Windows: combine "home" "bob" == "home\\bob" | ||||||||
(</>) :: FilePath -> FilePath -> FilePath | ||||||||
A nice alias for combine. | ||||||||
splitPath :: FilePath -> [FilePath] | ||||||||
Split a path by the directory separator. 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"] | ||||||||
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 (makeValid x)) `equalFilePath` makeValid x splitDirectories "" == [] | ||||||||
File name manipulators | ||||||||
normalise :: FilePath -> FilePath | ||||||||
Normalise a file
Posix: normalise "/file/\\test////" == "/file/\\test/" Posix: normalise "/file/./test" == "/file/test" Posix: normalise "/test/file/../bob/fred/" == "/test/file/../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 System.Directory.canonicalizePath first this has a much better chance of working. Note that this doesn't follow symlinks or DOSNAM~1s. | ||||||||
makeRelativeToCurrentDirectory :: FilePath -> IO FilePath | ||||||||
makeRelative the current directory. | ||||||||
makeRelative :: FilePath -> FilePath -> FilePath | ||||||||
Contract a filename, based on a relative path. Posix: makeRelative "/home/" "/home/bob/foo/bar" == "bob/foo/bar" Posix: makeRelative "/fred" "bob" == "bob" Posix: makeRelative "/file/test" "/file/test/fred" == "fred" Posix: makeRelative "/file/test" "/file/test/fred/" == "fred/" Posix: makeRelative "/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" | ||||||||
Produced by Haddock version 0.8 |