module Shelly.Find
(
find, findWhen, findFold, findDirFilter, findDirFilterWhen, findFoldDirFilter
) where
import Prelude hiding (FilePath)
import Shelly.Base
import Control.Monad (foldM)
import Data.Monoid (mappend)
import System.PosixCompat.Files( getSymbolicLinkStatus, isSymbolicLink )
import Filesystem (isDirectory)
find :: FilePath -> ShIO [FilePath]
find dir = findFold dir [] (\paths fp -> return $ paths ++ [fp])
findWhen :: FilePath -> (FilePath -> ShIO Bool) -> ShIO [FilePath]
findWhen dir filt = findDirFilterWhen dir (const $ return True) filt
findFold :: FilePath -> a -> (a -> FilePath -> ShIO a) -> ShIO a
findFold fp = findFoldDirFilter fp (const $ return True)
findDirFilter :: FilePath -> (FilePath -> ShIO Bool) -> ShIO [FilePath]
findDirFilter dir filt = findDirFilterWhen dir filt (const $ return True)
findDirFilterWhen :: FilePath
-> (FilePath -> ShIO Bool)
-> (FilePath -> ShIO Bool)
-> ShIO [FilePath]
findDirFilterWhen dir dirFilt fileFilter = findFoldDirFilter dir dirFilt [] filterIt
where
filterIt paths fp = do
yes <- fileFilter fp
return $ if yes then paths ++ [fp] else paths
findFoldDirFilter :: FilePath -> (FilePath -> ShIO Bool) -> a -> (a -> FilePath -> ShIO a) -> ShIO a
findFoldDirFilter dir dirFilter startValue folder = do
absDir <- absPath dir
trace ("find " `mappend` toTextIgnore absDir)
filt <- dirFilter absDir
if filt
then ls dir >>= foldM traverse startValue
else return startValue
where
traverse acc x = do
isDir <- liftIO $ isDirectory x
sym <- liftIO $ fmap isSymbolicLink $ getSymbolicLinkStatus (unpack x)
if isDir && not sym
then findFold x acc folder
else folder acc x