{-# LANGUAGE RankNTypes #-} module Data.Conduit.Filesystem ( sourceDirectory , sourceDirectoryDeep ) where import Data.Conduit import Control.Monad.Trans.Resource (MonadResource) import Control.Monad.IO.Class (liftIO) import System.FilePath (()) import qualified Data.Streaming.Filesystem as F -- | Stream the contents of the given directory, without traversing deeply. -- -- This function will return /all/ of the contents of the directory, whether -- they be files, directories, etc. -- -- Note that the generated filepaths will be the complete path, not just the -- filename. In other words, if you have a directory @foo@ containing files -- @bar@ and @baz@, and you use @sourceDirectory@ on @foo@, the results will be -- @foo/bar@ and @foo/baz@. -- -- Since 1.1.0 sourceDirectory :: MonadResource m => FilePath -> Producer m FilePath sourceDirectory dir = bracketP (F.openDirStream dir) F.closeDirStream go where go ds = loop where loop = do mfp <- liftIO $ F.readDirStream ds case mfp of Nothing -> return () Just fp -> do yield $ dir fp loop -- | Deeply stream the contents of the given directory. -- -- This works the same as @sourceDirectory@, but will not return directories at -- all. This function also takes an extra parameter to indicate whether -- symlinks will be followed. -- -- Since 1.1.0 sourceDirectoryDeep :: MonadResource m => Bool -- ^ Follow directory symlinks -> FilePath -- ^ Root directory -> Producer m FilePath sourceDirectoryDeep followSymlinks = start where start :: MonadResource m => FilePath -> Producer m FilePath start dir = sourceDirectory dir =$= awaitForever go go :: MonadResource m => FilePath -> Producer m FilePath go fp = do ft <- liftIO $ F.getFileType fp case ft of F.FTFile -> yield fp F.FTFileSym -> yield fp F.FTDirectory -> start fp F.FTDirectorySym | followSymlinks -> start fp | otherwise -> return () F.FTOther -> return ()