add flag to follow symlinks when recursing
This commit is contained in:
parent
1ed1659a64
commit
0edef8f7bb
1 changed files with 61 additions and 17 deletions
|
@ -45,11 +45,15 @@ module System.FilePath.Find (
|
||||||
|
|
||||||
-- * Simple entry points
|
-- * Simple entry points
|
||||||
, find
|
, find
|
||||||
|
, findL
|
||||||
, fold
|
, fold
|
||||||
|
, foldL
|
||||||
|
|
||||||
-- * More expressive entry points
|
-- * More expressive entry points
|
||||||
, findWithHandler
|
, findWithHandler
|
||||||
|
, findWithHandlerL
|
||||||
, foldWithHandler
|
, foldWithHandler
|
||||||
|
, foldWithHandlerL
|
||||||
|
|
||||||
-- * Helper functions
|
-- * Helper functions
|
||||||
, evalClause
|
, evalClause
|
||||||
|
@ -215,15 +219,16 @@ getDirContents dir = (sort . filter goodName) `liftM` getDirectoryContents dir
|
||||||
-- 'RecursionPredicate'. Lazily return a sorted list of all files
|
-- 'RecursionPredicate'. Lazily return a sorted list of all files
|
||||||
-- matching the given 'FilterPredicate'. Any errors that occur are
|
-- matching the given 'FilterPredicate'. Any errors that occur are
|
||||||
-- dealt with by the given handler.
|
-- dealt with by the given handler.
|
||||||
findWithHandler ::
|
findWithHandlerL ::
|
||||||
(FilePath -> IOException -> IO [FilePath]) -- ^ error handler
|
Bool -- ^ follow symlinks
|
||||||
|
-> (FilePath -> IOException -> IO [FilePath]) -- ^ error handler
|
||||||
-> RecursionPredicate -- ^ control recursion into subdirectories
|
-> RecursionPredicate -- ^ control recursion into subdirectories
|
||||||
-> FilterPredicate -- ^ decide whether a file appears in the result
|
-> FilterPredicate -- ^ decide whether a file appears in the result
|
||||||
-> FilePath -- ^ directory to start searching
|
-> FilePath -- ^ directory to start searching
|
||||||
-> IO [FilePath] -- ^ files that matched the 'FilterPredicate'
|
-> IO [FilePath] -- ^ files that matched the 'FilterPredicate'
|
||||||
|
|
||||||
findWithHandler errHandler recurse filt path0 =
|
findWithHandlerL links errHandler recurse filt path0 =
|
||||||
handle (errHandler path0) $ F.getSymbolicLinkStatus path0 >>= visit path0 0
|
handle (errHandler path0) $ getStatus links path0 >>= visit path0 0
|
||||||
where visit path depth st =
|
where visit path depth st =
|
||||||
if F.isDirectory st && evalFI recurse path depth st
|
if F.isDirectory st && evalFI recurse path depth st
|
||||||
then unsafeInterleaveIO (traverse path (succ depth) st)
|
then unsafeInterleaveIO (traverse path (succ depth) st)
|
||||||
|
@ -240,18 +245,38 @@ findWithHandler errHandler recurse filt path0 =
|
||||||
then path:result
|
then path:result
|
||||||
else result
|
else result
|
||||||
|
|
||||||
|
getStatus :: Bool -> FilePath -> IO F.FileStatus
|
||||||
|
getStatus links = if links then F.getFileStatus else F.getSymbolicLinkStatus
|
||||||
|
|
||||||
|
-- | Same as 'findWithHandlerL' without following links
|
||||||
|
findWithHandler ::
|
||||||
|
(FilePath -> IOException -> IO [FilePath]) -- ^ error handler
|
||||||
|
-> RecursionPredicate -- ^ control recursion into subdirectories
|
||||||
|
-> FilterPredicate -- ^ decide whether a file appears in the result
|
||||||
|
-> FilePath -- ^ directory to start searching
|
||||||
|
-> IO [FilePath] -- ^ files that matched the 'FilterPredicate'
|
||||||
|
findWithHandler = findWithHandlerL False
|
||||||
|
|
||||||
-- | Search a directory recursively, with recursion controlled by a
|
-- | Search a directory recursively, with recursion controlled by a
|
||||||
-- 'RecursionPredicate'. Lazily return a sorted list of all files
|
-- 'RecursionPredicate'. Lazily return a sorted list of all files
|
||||||
-- matching the given 'FilterPredicate'. Any errors that occur are
|
-- matching the given 'FilterPredicate'. Any errors that occur are
|
||||||
-- ignored, with warnings printed to 'stderr'.
|
-- ignored, with warnings printed to 'stderr'.
|
||||||
|
findL :: Bool -- ^ follow symlinks
|
||||||
|
-> RecursionPredicate -- ^ control recursion into subdirectories
|
||||||
|
-> FilterPredicate -- ^ decide whether a file appears in the result
|
||||||
|
-> FilePath -- ^ directory to start searching
|
||||||
|
-> IO [FilePath] -- ^ files that matched the 'FilterPredicate'
|
||||||
|
|
||||||
|
findL links = findWithHandlerL links warnOnError
|
||||||
|
where warnOnError path err =
|
||||||
|
hPutStrLn stderr (path ++ ": " ++ show err) >> return []
|
||||||
|
|
||||||
|
-- | Same as 'findL' without following links
|
||||||
find :: RecursionPredicate -- ^ control recursion into subdirectories
|
find :: RecursionPredicate -- ^ control recursion into subdirectories
|
||||||
-> FilterPredicate -- ^ decide whether a file appears in the result
|
-> FilterPredicate -- ^ decide whether a file appears in the result
|
||||||
-> FilePath -- ^ directory to start searching
|
-> FilePath -- ^ directory to start searching
|
||||||
-> IO [FilePath] -- ^ files that matched the 'FilterPredicate'
|
-> IO [FilePath] -- ^ files that matched the 'FilterPredicate'
|
||||||
|
find = findL False
|
||||||
find = findWithHandler warnOnError
|
|
||||||
where warnOnError path err =
|
|
||||||
hPutStrLn stderr (path ++ ": " ++ show err) >> return []
|
|
||||||
|
|
||||||
-- | Search a directory recursively, with recursion controlled by a
|
-- | Search a directory recursively, with recursion controlled by a
|
||||||
-- 'RecursionPredicate'. Fold over all files found. Any errors that
|
-- 'RecursionPredicate'. Fold over all files found. Any errors that
|
||||||
|
@ -260,17 +285,17 @@ find = findWithHandler warnOnError
|
||||||
-- strict in its left argument to avoid space leaks. If you need a
|
-- strict in its left argument to avoid space leaks. If you need a
|
||||||
-- right-to-left fold, use 'foldr' on the result of 'findWithHandler'
|
-- right-to-left fold, use 'foldr' on the result of 'findWithHandler'
|
||||||
-- instead.
|
-- instead.
|
||||||
foldWithHandler
|
foldWithHandlerL
|
||||||
:: (FilePath -> a -> IOException -> IO a) -- ^ error handler
|
:: Bool -- ^ follow symlinks
|
||||||
|
-> (FilePath -> a -> IOException -> IO a) -- ^ error handler
|
||||||
-> RecursionPredicate -- ^ control recursion into subdirectories
|
-> RecursionPredicate -- ^ control recursion into subdirectories
|
||||||
-> (a -> FileInfo -> a) -- ^ function to fold with
|
-> (a -> FileInfo -> a) -- ^ function to fold with
|
||||||
-> a -- ^ seed value for fold
|
-> a -- ^ seed value for fold
|
||||||
-> FilePath -- ^ directory to start searching
|
-> FilePath -- ^ directory to start searching
|
||||||
-> IO a -- ^ final value after folding
|
-> IO a -- ^ final value after folding
|
||||||
|
|
||||||
foldWithHandler errHandler recurse f state path =
|
foldWithHandlerL links errHandler recurse f state path =
|
||||||
handle (errHandler path state) $
|
handle (errHandler path state) $ getStatus links path >>= visit state path 0
|
||||||
F.getSymbolicLinkStatus path >>= visit state path 0
|
|
||||||
where visit state path depth st =
|
where visit state path depth st =
|
||||||
if F.isDirectory st && evalFI recurse path depth st
|
if F.isDirectory st && evalFI recurse path depth st
|
||||||
then traverse state path (succ depth) st
|
then traverse state path (succ depth) st
|
||||||
|
@ -284,6 +309,16 @@ foldWithHandler errHandler recurse f state path =
|
||||||
let path = dir </> name
|
let path = dir </> name
|
||||||
in F.getSymbolicLinkStatus path >>= visit state path depth)
|
in F.getSymbolicLinkStatus path >>= visit state path depth)
|
||||||
|
|
||||||
|
-- | Same as 'foldWithHandlerL' without following symlinks
|
||||||
|
foldWithHandler
|
||||||
|
:: (FilePath -> a -> IOException -> IO a) -- ^ error handler
|
||||||
|
-> RecursionPredicate -- ^ control recursion into subdirectories
|
||||||
|
-> (a -> FileInfo -> a) -- ^ function to fold with
|
||||||
|
-> a -- ^ seed value for fold
|
||||||
|
-> FilePath -- ^ directory to start searching
|
||||||
|
-> IO a -- ^ final value after folding
|
||||||
|
foldWithHandler = foldWithHandlerL False
|
||||||
|
|
||||||
-- | Search a directory recursively, with recursion controlled by a
|
-- | Search a directory recursively, with recursion controlled by a
|
||||||
-- 'RecursionPredicate'. Fold over all files found. Any errors that
|
-- 'RecursionPredicate'. Fold over all files found. Any errors that
|
||||||
-- occur are ignored, with warnings printed to 'stderr'. The fold
|
-- occur are ignored, with warnings printed to 'stderr'. The fold
|
||||||
|
@ -291,15 +326,24 @@ foldWithHandler errHandler recurse f state path =
|
||||||
-- in its left argument to avoid space leaks. If you need a
|
-- in its left argument to avoid space leaks. If you need a
|
||||||
-- right-to-left fold, use 'foldr' on the result of 'findWithHandler'
|
-- right-to-left fold, use 'foldr' on the result of 'findWithHandler'
|
||||||
-- instead.
|
-- instead.
|
||||||
|
foldL :: Bool -- ^ follow symlinks
|
||||||
|
-> RecursionPredicate
|
||||||
|
-> (a -> FileInfo -> a)
|
||||||
|
-> a
|
||||||
|
-> FilePath
|
||||||
|
-> IO a
|
||||||
|
|
||||||
|
foldL links = foldWithHandlerL links warnOnError
|
||||||
|
where warnOnError path a err =
|
||||||
|
hPutStrLn stderr (path ++ ": " ++ show err) >> return a
|
||||||
|
|
||||||
|
-- | 'foldL' without following symlinks
|
||||||
fold :: RecursionPredicate
|
fold :: RecursionPredicate
|
||||||
-> (a -> FileInfo -> a)
|
-> (a -> FileInfo -> a)
|
||||||
-> a
|
-> a
|
||||||
-> FilePath
|
-> FilePath
|
||||||
-> IO a
|
-> IO a
|
||||||
|
fold = foldL False
|
||||||
fold = foldWithHandler warnOnError
|
|
||||||
where warnOnError path a err =
|
|
||||||
hPutStrLn stderr (path ++ ": " ++ show err) >> return a
|
|
||||||
|
|
||||||
-- | Unconditionally return 'True'.
|
-- | Unconditionally return 'True'.
|
||||||
always :: FindClause Bool
|
always :: FindClause Bool
|
||||||
|
|
Loading…
Add table
Reference in a new issue