{-# LANGUAGE OverloadedStrings #-}
module Shelly.Find
( find
, findWhen
, findFold
, findDirFilter
, findDirFilterWhen
, findFoldDirFilter
)
where
import Shelly.Base
import Control.Monad ( foldM )
#if !MIN_VERSION_base(4,13,0)
import Data.Monoid ( mappend )
#endif
import System.PosixCompat.Files ( getSymbolicLinkStatus
, isSymbolicLink
)
import System.Directory ( doesDirectoryExist )
find :: FilePath -> Sh [FilePath]
find :: FilePath -> Sh [FilePath]
find = ([FilePath] -> FilePath -> Sh [FilePath])
-> [FilePath] -> FilePath -> Sh [FilePath]
forall a. (a -> FilePath -> Sh a) -> a -> FilePath -> Sh a
findFold (\[FilePath]
paths FilePath
fp -> [FilePath] -> Sh [FilePath]
forall a. a -> Sh a
forall (m :: * -> *) a. Monad m => a -> m a
return ([FilePath] -> Sh [FilePath]) -> [FilePath] -> Sh [FilePath]
forall a b. (a -> b) -> a -> b
$ [FilePath]
paths [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ [FilePath
fp]) []
findWhen :: (FilePath -> Sh Bool) -> FilePath -> Sh [FilePath]
findWhen :: (FilePath -> Sh Bool) -> FilePath -> Sh [FilePath]
findWhen = (FilePath -> Sh Bool)
-> (FilePath -> Sh Bool) -> FilePath -> Sh [FilePath]
findDirFilterWhen (Sh Bool -> FilePath -> Sh Bool
forall a b. a -> b -> a
const (Sh Bool -> FilePath -> Sh Bool) -> Sh Bool -> FilePath -> Sh Bool
forall a b. (a -> b) -> a -> b
$ Bool -> Sh Bool
forall a. a -> Sh a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True)
findFold :: (a -> FilePath -> Sh a) -> a -> FilePath -> Sh a
findFold :: forall a. (a -> FilePath -> Sh a) -> a -> FilePath -> Sh a
findFold a -> FilePath -> Sh a
folder a
startValue =
(a -> FilePath -> Sh a)
-> a -> (FilePath -> Sh Bool) -> FilePath -> Sh a
forall a.
(a -> FilePath -> Sh a)
-> a -> (FilePath -> Sh Bool) -> FilePath -> Sh a
findFoldDirFilter a -> FilePath -> Sh a
folder a
startValue (Sh Bool -> FilePath -> Sh Bool
forall a b. a -> b -> a
const (Sh Bool -> FilePath -> Sh Bool) -> Sh Bool -> FilePath -> Sh Bool
forall a b. (a -> b) -> a -> b
$ Bool -> Sh Bool
forall a. a -> Sh a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True)
findDirFilter :: (FilePath -> Sh Bool) -> FilePath -> Sh [FilePath]
findDirFilter :: (FilePath -> Sh Bool) -> FilePath -> Sh [FilePath]
findDirFilter FilePath -> Sh Bool
filt = (FilePath -> Sh Bool)
-> (FilePath -> Sh Bool) -> FilePath -> Sh [FilePath]
findDirFilterWhen FilePath -> Sh Bool
filt (Sh Bool -> FilePath -> Sh Bool
forall a b. a -> b -> a
const (Sh Bool -> FilePath -> Sh Bool) -> Sh Bool -> FilePath -> Sh Bool
forall a b. (a -> b) -> a -> b
$ Bool -> Sh Bool
forall a. a -> Sh a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True)
findDirFilterWhen
:: (FilePath -> Sh Bool)
-> (FilePath -> Sh Bool)
-> FilePath
-> Sh [FilePath]
findDirFilterWhen :: (FilePath -> Sh Bool)
-> (FilePath -> Sh Bool) -> FilePath -> Sh [FilePath]
findDirFilterWhen FilePath -> Sh Bool
dirFilt FilePath -> Sh Bool
fileFilter = ([FilePath] -> FilePath -> Sh [FilePath])
-> [FilePath] -> (FilePath -> Sh Bool) -> FilePath -> Sh [FilePath]
forall a.
(a -> FilePath -> Sh a)
-> a -> (FilePath -> Sh Bool) -> FilePath -> Sh a
findFoldDirFilter [FilePath] -> FilePath -> Sh [FilePath]
filterIt [] FilePath -> Sh Bool
dirFilt
where
filterIt :: [FilePath] -> FilePath -> Sh [FilePath]
filterIt [FilePath]
paths FilePath
fp = do
yes <- FilePath -> Sh Bool
fileFilter FilePath
fp
return $ if yes then paths ++ [fp] else paths
findFoldDirFilter
:: (a -> FilePath -> Sh a) -> a -> (FilePath -> Sh Bool) -> FilePath -> Sh a
findFoldDirFilter :: forall a.
(a -> FilePath -> Sh a)
-> a -> (FilePath -> Sh Bool) -> FilePath -> Sh a
findFoldDirFilter a -> FilePath -> Sh a
folder a
startValue FilePath -> Sh Bool
dirFilter FilePath
dir = do
absDir <- FilePath -> Sh FilePath
absPath FilePath
dir
trace ("find " `mappend` toTextIgnore absDir)
filt <- dirFilter absDir
if not filt
then return startValue
else do
(rPaths, aPaths) <- lsRelAbs dir
foldM traverse' startValue (zip rPaths aPaths)
where
traverse' :: a -> (FilePath, FilePath) -> Sh a
traverse' a
acc (FilePath
relativePath, FilePath
absolutePath) = do
isDir <- IO Bool -> Sh Bool
forall a. IO a -> Sh a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Bool -> Sh Bool) -> IO Bool -> Sh Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesDirectoryExist FilePath
absolutePath
sym <- liftIO $ fmap isSymbolicLink $ getSymbolicLinkStatus absolutePath
newAcc <- folder acc relativePath
follow <- fmap sFollowSymlink get
if isDir && (follow || not sym)
then findFoldDirFilter folder newAcc dirFilter relativePath
else return newAcc