Add Glob module, update docs.
--HG-- extra : convert_revision : e114cb9154838d7f74c72671db22dbddb97e3a58
This commit is contained in:
parent
cb63c4f2a5
commit
097afc9831
5 changed files with 110 additions and 3 deletions
72
System/FilePath/Glob.hs
Normal file
72
System/FilePath/Glob.hs
Normal file
|
@ -0,0 +1,72 @@
|
|||
-- |
|
||||
-- Module: System.FilePath.Glob
|
||||
-- Copyright: Bryan O'Sullivan
|
||||
-- License: LGPL
|
||||
-- Maintainer: Bryan O'Sullivan <bos@serpentine.com>
|
||||
-- Stability: unstable
|
||||
-- Portability: everywhere
|
||||
|
||||
module System.FilePath.Glob (
|
||||
namesMatching
|
||||
) where
|
||||
|
||||
import Control.Exception (handle)
|
||||
import Control.Monad (forM)
|
||||
import System.FilePath.GlobPattern ((~~))
|
||||
import System.Directory (doesDirectoryExist, doesFileExist,
|
||||
getCurrentDirectory, getDirectoryContents)
|
||||
import System.FilePath (dropTrailingPathSeparator, splitFileName, (</>))
|
||||
import System.IO.Unsafe (unsafeInterleaveIO)
|
||||
|
||||
-- | Return a list of names matching a glob pattern. The list is
|
||||
-- generated lazily.
|
||||
namesMatching :: String -> IO [FilePath]
|
||||
namesMatching pat
|
||||
| not (isPattern pat) = do
|
||||
exists <- doesNameExist pat
|
||||
return (if exists then [pat] else [])
|
||||
| otherwise = do
|
||||
case splitFileName pat of
|
||||
("", baseName) -> do
|
||||
curDir <- getCurrentDirectory
|
||||
listMatches curDir baseName
|
||||
(dirName, baseName) -> do
|
||||
dirs <- if isPattern dirName
|
||||
then namesMatching (dropTrailingPathSeparator dirName)
|
||||
else return [dirName]
|
||||
let listDir = if isPattern baseName
|
||||
then listMatches
|
||||
else listPlain
|
||||
pathNames <- forM dirs $ \dir -> do
|
||||
baseNames <- listDir dir baseName
|
||||
return (map (dir </>) baseNames)
|
||||
return (concat pathNames)
|
||||
where isPattern = any (`elem` "[*?")
|
||||
|
||||
listMatches :: FilePath -> String -> IO [String]
|
||||
listMatches dirName pat = do
|
||||
dirName' <- if null dirName
|
||||
then getCurrentDirectory
|
||||
else return dirName
|
||||
names <- unsafeInterleaveIO (handle (const (return [])) $
|
||||
getDirectoryContents dirName')
|
||||
let names' = if isHidden pat
|
||||
then filter isHidden names
|
||||
else filter (not . isHidden) names
|
||||
return (filter (~~ pat) names')
|
||||
where isHidden ('.':_) = True
|
||||
isHidden _ = False
|
||||
|
||||
listPlain :: FilePath -> String -> IO [String]
|
||||
listPlain dirName baseName = do
|
||||
exists <- if null baseName
|
||||
then doesDirectoryExist dirName
|
||||
else doesNameExist (dirName </> baseName)
|
||||
return (if exists then [baseName] else [])
|
||||
|
||||
doesNameExist :: FilePath -> IO Bool
|
||||
doesNameExist name = do
|
||||
fileExists <- doesFileExist name
|
||||
if fileExists
|
||||
then return True
|
||||
else doesDirectoryExist name
|
Loading…
Add table
Add a link
Reference in a new issue