Safe Haskell | None |
---|---|
Language | Haskell2010 |
Data.Conduit.Find
Synopsis
- sourceFindFiles :: forall (m :: Type -> Type) a i. MonadResource m => FindOptions -> FilePath -> CondT FileEntry m a -> ConduitT i (FileEntry, a) m ()
- find :: forall (m :: Type -> Type) a i. MonadResource m => FilePath -> CondT FileEntry m a -> ConduitT i FilePath m ()
- findFiles :: (MonadIO m, MonadBaseControl IO m, MonadThrow m, MonadUnliftIO m) => FindOptions -> FilePath -> CondT FileEntry m a -> m ()
- findFilePaths :: forall (m :: Type -> Type) a i. (MonadIO m, MonadResource m) => FindOptions -> FilePath -> CondT FileEntry m a -> ConduitT i FilePath m ()
- data FindOptions = FindOptions {}
- defaultFindOptions :: FindOptions
- test :: MonadIO m => CondT FileEntry m () -> FilePath -> m Bool
- ltest :: MonadIO m => CondT FileEntry m () -> FilePath -> m Bool
- stat :: forall (m :: Type -> Type). MonadIO m => CondT FileEntry m FileStatus
- lstat :: forall (m :: Type -> Type). MonadIO m => CondT FileEntry m FileStatus
- hasStatus :: forall (m :: Type -> Type). MonadIO m => (FileStatus -> Bool) -> CondT FileEntry m ()
- glob :: forall (m :: Type -> Type). Monad m => String -> CondT FileEntry m ()
- regex :: forall (m :: Type -> Type). Monad m => String -> CondT FileEntry m ()
- ignoreVcs :: forall (m :: Type -> Type). Monad m => CondT FileEntry m ()
- depth_ :: forall (m :: Type -> Type). Monad m => CondT FileEntry m ()
- follow_ :: forall (m :: Type -> Type). Monad m => CondT FileEntry m ()
- noleaf_ :: forall (m :: Type -> Type). Monad m => CondT FileEntry m ()
- prune_ :: forall (m :: Type -> Type) a. Monad m => CondT a m ()
- maxdepth_ :: forall (m :: Type -> Type). Monad m => Int -> CondT FileEntry m ()
- mindepth_ :: forall (m :: Type -> Type). Monad m => Int -> CondT FileEntry m ()
- ignoreErrors_ :: forall (m :: Type -> Type). Monad m => CondT FileEntry m ()
- noIgnoreErrors_ :: forall (m :: Type -> Type). Monad m => CondT FileEntry m ()
- amin_ :: forall (m :: Type -> Type). MonadIO m => Int -> CondT FileEntry m ()
- atime_ :: forall (m :: Type -> Type). MonadIO m => Int -> CondT FileEntry m ()
- anewer_ :: forall (m :: Type -> Type). MonadIO m => FilePath -> CondT FileEntry m ()
- empty_ :: forall (m :: Type -> Type). MonadIO m => CondT FileEntry m ()
- executable_ :: forall (m :: Type -> Type). MonadIO m => CondT FileEntry m ()
- gid_ :: forall (m :: Type -> Type). MonadIO m => Int -> CondT FileEntry m ()
- name_ :: forall (m :: Type -> Type). Monad m => FilePath -> CondT FileEntry m ()
- getDepth :: forall (m :: Type -> Type). Monad m => CondT FileEntry m Int
- filename_ :: forall (m :: Type -> Type). Monad m => (FilePath -> Bool) -> CondT FileEntry m ()
- pathname_ :: forall (m :: Type -> Type). Monad m => (FilePath -> Bool) -> CondT FileEntry m ()
- getFilePath :: forall (m :: Type -> Type). Monad m => CondT FileEntry m FilePath
- regular :: forall (m :: Type -> Type). MonadIO m => CondT FileEntry m ()
- directory :: forall (m :: Type -> Type). MonadIO m => CondT FileEntry m ()
- hasMode :: forall (m :: Type -> Type). MonadIO m => FileMode -> CondT FileEntry m ()
- executable :: forall (m :: Type -> Type). MonadIO m => CondT FileEntry m ()
- lastAccessed_ :: forall (m :: Type -> Type). MonadIO m => (UTCTime -> Bool) -> CondT FileEntry m ()
- lastModified_ :: forall (m :: Type -> Type). MonadIO m => (UTCTime -> Bool) -> CondT FileEntry m ()
- apply :: Monad m => (a -> m (Maybe b)) -> CondT a m b
- ignore :: forall (m :: Type -> Type) a b. Monad m => CondT a m b
- newtype CondT a (m :: Type -> Type) b = CondT {}
- type Cond a = CondT a Identity
- runCondT :: Monad m => CondT a m b -> a -> m (Maybe b)
- runCond :: Cond a b -> a -> Maybe b
- applyCondT :: Monad m => a -> CondT a m b -> m ((Maybe b, Maybe (CondT a m b)), a)
- applyCond :: a -> Cond a b -> ((Maybe b, Maybe (Cond a b)), a)
- guardM :: Monad m => m Bool -> CondT a m ()
- guard_ :: forall (m :: Type -> Type) a. Monad m => (a -> Bool) -> CondT a m ()
- guardM_ :: Monad m => (a -> m Bool) -> CondT a m ()
- consider :: Monad m => (a -> m (Maybe (b, a))) -> CondT a m b
- matches :: forall (m :: Type -> Type) a b. Monad m => CondT a m b -> CondT a m Bool
- if_ :: forall (m :: Type -> Type) a r b. Monad m => CondT a m r -> CondT a m b -> CondT a m b -> CondT a m b
- when_ :: forall (m :: Type -> Type) a r. Monad m => CondT a m r -> CondT a m () -> CondT a m ()
- unless_ :: forall (m :: Type -> Type) a r. Monad m => CondT a m r -> CondT a m () -> CondT a m ()
- or_ :: forall (m :: Type -> Type) a b. Monad m => [CondT a m b] -> CondT a m b
- and_ :: forall (m :: Type -> Type) a b. Monad m => [CondT a m b] -> CondT a m ()
- not_ :: forall (m :: Type -> Type) a b. Monad m => CondT a m b -> CondT a m ()
- norecurse :: forall (m :: Type -> Type) a. Monad m => CondT a m ()
- prune :: forall (m :: Type -> Type) a b. Monad m => CondT a m b
- recurse :: forall (m :: Type -> Type) a b. Monad m => CondT a m b -> CondT a m b
- newtype CondEitherT a (m :: Type -> Type) b = CondEitherT (StateT a (EitherT (Maybe (Maybe (CondEitherT a m b))) m) (b, Maybe (Maybe (CondEitherT a m b))))
- fromCondT :: forall (m :: Type -> Type) a b. Monad m => CondT a m b -> CondEitherT a m b
- toCondT :: forall (m :: Type -> Type) a b. Monad m => CondEitherT a m b -> CondT a m b
- (=~) :: (RegexMaker Regex CompOption ExecOption source, RegexContext Regex source1 target) => source1 -> source -> target
- data FileEntry = FileEntry {
- entryPath :: !FilePath
- entryDepth :: !Int
- entryFindOptions :: !FindOptions
- entryStatus :: !(Maybe FileStatus)
Introduction
- *find-conduit** is essentially a souped version of GNU find for Haskell, using a DSL to provide both ease of us, and extensive flexbility.
In its simplest form, let's compare some uses of find to find-conduit. Bear in mind that the result of the find function is a conduit, so you're expected to either sink it to a list, or operate on the file paths as they are yielded.
Basic comparison with GNU find
A typical find command:
find src -name '*.hs' -type f -print
Would in find-conduit be:
find "src" (glob "*.hs" <> regular) $$ mapM_C (liftIO . print)
The glob
predicate matches the file basename against the globbing pattern,
while the regular
predicate matches plain files.
A more complicated example:
find . -size +100M -perm 644 -mtime 1
Now in find-conduit:
let megs = 1024 * 1024 days = 86400 now <- liftIO getCurrentTime find "." ( fileSize (> 100*megs) <> hasMode 0o644 <> lastModified (> addUTCTime now (-(1*days))) )
Appending predicates like this expressing an "and" relationship. Use <|>
to
express "or". You can also negate any predicate:
find "." (not_ (hasMode 0o644))
By default, predicates, whether matching or not, will allow recursion into
directories. In order to express that matching predicate should disallow
recursion, use prune
:
find "." (prune (depth (> 2)))
This is the same as using '-maxdepth 2' in find.
find "." (prune (filename_ (== "dist")))
This is the same as:
find . \( -name dist -prune \) -o -print
Performance
find-conduit strives to make file-finding a well performing operation. To this end, a composed Predicate will only call stat once per entry being considered; and if you prune a directory, it is not traversed at all.
By default, find
calls stat for every file before it applies the predicate,
in order to ensure that only one such call is needed. Sometimes, however, you
know just from the FilePath that you don't want to consider a certain file, or
you want to prune a directory tree.
To support these types of optimized queries, a variant of find is provided
called findWithPreFilter
. This takes two predicates: one that is applied to
only the FilePath, before stat (or lstat) is called; and one that is applied
to the full file information after the stat.
Other notes
See Cond
for more details on the Monad used to build predicates.
Finding functions
sourceFindFiles :: forall (m :: Type -> Type) a i. MonadResource m => FindOptions -> FilePath -> CondT FileEntry m a -> ConduitT i (FileEntry, a) m () Source #
Find file entries in a directory tree, recursively, applying the given
recursion predicate to the search. This conduit yields pairs of type
(FileEntry, a)
, where is the return value from the predicate at each
step.
find :: forall (m :: Type -> Type) a i. MonadResource m => FilePath -> CondT FileEntry m a -> ConduitT i FilePath m () Source #
Calls findFilePaths
with the default set of finding options.
Equivalent to findFilePaths defaultFindOptions
.
findFiles :: (MonadIO m, MonadBaseControl IO m, MonadThrow m, MonadUnliftIO m) => FindOptions -> FilePath -> CondT FileEntry m a -> m () Source #
findFilePaths :: forall (m :: Type -> Type) a i. (MonadIO m, MonadResource m) => FindOptions -> FilePath -> CondT FileEntry m a -> ConduitT i FilePath m () Source #
data FindOptions Source #
Constructors
FindOptions | |
Fields
|
test :: MonadIO m => CondT FileEntry m () -> FilePath -> m Bool Source #
Test a file path using the same type of predicate that is accepted by
findFiles
.
ltest :: MonadIO m => CondT FileEntry m () -> FilePath -> m Bool Source #
Test a file path using the same type of predicate that is accepted by
findFiles
, but do not follow symlinks.
hasStatus :: forall (m :: Type -> Type). MonadIO m => (FileStatus -> Bool) -> CondT FileEntry m () Source #
File path predicates
glob :: forall (m :: Type -> Type). Monad m => String -> CondT FileEntry m () Source #
Find every entry whose filename part matching the given filename globbing
expression. For example: glob "*.hs"
.
ignoreVcs :: forall (m :: Type -> Type). Monad m => CondT FileEntry m () Source #
Return all entries, except for those within version-control metadata directories (and not including the version control directory itself either).
GNU find compatibility predicates
filename_ :: forall (m :: Type -> Type). Monad m => (FilePath -> Bool) -> CondT FileEntry m () Source #
pathname_ :: forall (m :: Type -> Type). Monad m => (FilePath -> Bool) -> CondT FileEntry m () Source #
File entry predicates (uses stat information)
lastAccessed_ :: forall (m :: Type -> Type). MonadIO m => (UTCTime -> Bool) -> CondT FileEntry m () Source #
lastModified_ :: forall (m :: Type -> Type). MonadIO m => (UTCTime -> Bool) -> CondT FileEntry m () Source #
Predicate combinators
newtype CondT a (m :: Type -> Type) b Source #
CondT
is a kind of StateT a (MaybeT m) b
, which uses a special
Result
type instead of Maybe
to express whether recursion should be
performed from the item under consideration. This is used to build
predicates that can guide recursive traversals.
Several different types may be promoted to CondT
:
Bool
- Using
guard
m Bool
- Using
guardM
a -> Bool
- Using
guard_
a -> m Bool
- Using
guardM_
a -> m (Maybe b)
- Using
apply
a -> m (Maybe (b, a))
- Using
consider
Here is a trivial example:
flip runCondT 42 $ do guard_ even liftIO $ putStrLn "42 must be even to reach here" guard_ odd <|> guard_ even guard_ (== 42)
If CondT
is executed using runCondT
, it return a Maybe b
if the
predicate matched. It can also be run with applyCondT
, which does case
analysis on the Result
, specifying how recursion should be performed from
the given a
value.
Instances
applyCondT :: Monad m => a -> CondT a m b -> m ((Maybe b, Maybe (CondT a m b)), a) Source #
Case analysis of applying a condition to an input value. The result is a pair whose first part is a pair of Maybes specifying if the input matched and if recursion is expected from this value, and whose second part is the (possibly) mutated input value.
applyCond :: a -> Cond a b -> ((Maybe b, Maybe (Cond a b)), a) Source #
Case analysis of applying a pure condition to an input value. The result is a pair whose first part is a pair of Maybes specifying if the input matched and if recursion is expected from this value, and whose second part is the (possibly) mutated input value.
matches :: forall (m :: Type -> Type) a b. Monad m => CondT a m b -> CondT a m Bool Source #
Return True or False depending on whether the given condition matches or not. This differs from simply stating the condition in that it itself always succeeds.
>>>
flip runCond "foo.hs" $ matches (guard =<< asks (== "foo.hs"))
Just True>>>
flip runCond "foo.hs" $ matches (guard =<< asks (== "foo.hi"))
Just False
if_ :: forall (m :: Type -> Type) a r b. Monad m => CondT a m r -> CondT a m b -> CondT a m b -> CondT a m b Source #
A variant of ifM which branches on whether the condition succeeds or not.
Note that if_ x
is equivalent to ifM (matches x)
, and is provided
solely for convenience.
>>>
let good = guard_ (== "foo.hs") :: Cond String ()
>>>
let bad = guard_ (== "foo.hi") :: Cond String ()
>>>
flip runCond "foo.hs" $ if_ good (return "Success") (return "Failure")
Just "Success">>>
flip runCond "foo.hs" $ if_ bad (return "Success") (return "Failure")
Just "Failure"
when_ :: forall (m :: Type -> Type) a r. Monad m => CondT a m r -> CondT a m () -> CondT a m () Source #
when_
is just like when
, except that it executes the body if the
condition passes, rather than based on a Bool value.
>>>
let good = guard_ (== "foo.hs") :: Cond String ()
>>>
let bad = guard_ (== "foo.hi") :: Cond String ()
>>>
flip runCond "foo.hs" $ when_ good ignore
Nothing>>>
flip runCond "foo.hs" $ when_ bad ignore
Just ()
unless_ :: forall (m :: Type -> Type) a r. Monad m => CondT a m r -> CondT a m () -> CondT a m () Source #
when_
is just like when
, except that it executes the body if the
condition fails, rather than based on a Bool value.
>>>
let good = guard_ (== "foo.hs") :: Cond String ()
>>>
let bad = guard_ (== "foo.hi") :: Cond String ()
>>>
flip runCond "foo.hs" $ unless_ bad ignore
Nothing>>>
flip runCond "foo.hs" $ unless_ good ignore
Just ()
or_ :: forall (m :: Type -> Type) a b. Monad m => [CondT a m b] -> CondT a m b Source #
Check whether at least one of the given conditions is true. This is a
synonym for asum
.
>>>
let good = guard_ (== "foo.hs") :: Cond String ()
>>>
let bad = guard_ (== "foo.hi") :: Cond String ()
>>>
flip runCond "foo.hs" $ or_ [bad, good]
Just ()>>>
flip runCond "foo.hs" $ or_ [bad]
Nothing
and_ :: forall (m :: Type -> Type) a b. Monad m => [CondT a m b] -> CondT a m () Source #
Check that all of the given conditions are true. This is a synonym for
sequence_
.
>>>
let good = guard_ (== "foo.hs") :: Cond String ()
>>>
let bad = guard_ (== "foo.hi") :: Cond String ()
>>>
flip runCond "foo.hs" $ and_ [bad, good]
Nothing>>>
flip runCond "foo.hs" $ and_ [good]
Just ()
not_ :: forall (m :: Type -> Type) a b. Monad m => CondT a m b -> CondT a m () Source #
not_
inverts the meaning of the given predicate.
>>>
let good = guard_ (== "foo.hs") :: Cond String ()
>>>
let bad = guard_ (== "foo.hi") :: Cond String ()
>>>
flip runCond "foo.hs" $ not_ bad >> return "Success"
Just "Success">>>
flip runCond "foo.hs" $ not_ good >> return "Shouldn't reach here"
Nothing
norecurse :: forall (m :: Type -> Type) a. Monad m => CondT a m () Source #
norecurse
prevents recursion into the current entry's descendents, but
does not ignore the entry itself.
prune :: forall (m :: Type -> Type) a b. Monad m => CondT a m b Source #
prune
is a synonym for both ignoring an entry and its descendents. It
is the same as ignore >> norecurse
.
recurse :: forall (m :: Type -> Type) a b. Monad m => CondT a m b -> CondT a m b Source #
recurse
changes the recursion predicate for any child elements. For
example, the following file-finding predicate looks for all *.hs
files,
but under any .git
directory looks only for a file named config
:
if_ (name_ ".git" >> directory) (ignore >> recurse (name_ "config")) (glob "*.hs")
NOTE: If this code had used recurse (glob "*.hs"))
instead in the else
case, it would have meant that .git
is only looked for at the top-level
of the search (i.e., the top-most element).
newtype CondEitherT a (m :: Type -> Type) b Source #
This type is for documentation only, and shows the isomorphism between
CondT
and CondEitherT
. The reason for using Result
is that it
makes meaning of the constructors more explicit.
Constructors
CondEitherT (StateT a (EitherT (Maybe (Maybe (CondEitherT a m b))) m) (b, Maybe (Maybe (CondEitherT a m b)))) |
fromCondT :: forall (m :: Type -> Type) a b. Monad m => CondT a m b -> CondEitherT a m b Source #
Witness one half of the isomorphism from CondT
to CondEitherT
.
toCondT :: forall (m :: Type -> Type) a b. Monad m => CondEitherT a m b -> CondT a m b Source #
Witness the other half of the isomorphism from CondEitherT
to CondT
.
(=~) :: (RegexMaker Regex CompOption ExecOption source, RegexContext Regex source1 target) => source1 -> source -> target #
Types and type classes
Constructors
FileEntry | |
Fields
|