Chris Stryczynski
Chris Stryczynski

Reputation: 34091

Haskell get directories in directory

How can I get a list of directories that are in a directory?

I've come up with the below, but I'm hoping there is a more elegant way:

import System.Directory
import qualified Filesystem.Path as FsP
import Filesystem.Path.CurrentOS
import Control.Monad

getDirectories :: Prelude.FilePath -> IO [Prelude.FilePath]
getDirectories x = do
  listDirectory x
  >>= (return . fmap decodeString)
  >>= return . fmap (FsP.append (decodeString x))
  >>= (return . fmap encodeString)
  >>= filterM doesDirectoryExist

Upvotes: 2

Views: 1468

Answers (2)

basile-henry
basile-henry

Reputation: 1365

It looks like you are using the package system-filepath which is deprecated, how about using the filepath package instead:

import           Control.Monad    (filterM)
import           System.Directory (doesDirectoryExist, listDirectory)
import           System.FilePath  ((</>))

getDirectories :: FilePath -> IO [FilePath]
getDirectories filePath = do
  allFiles <- listDirectory filePath
  filterM (doesDirectoryExist . (filePath </>)) allFiles

Or if you prefer explicitly using the bind operator:

import           Control.Monad    (filterM)
import           System.Directory (doesDirectoryExist, listDirectory)
import           System.FilePath  ((</>))

getDirectories :: FilePath -> IO [FilePath]
getDirectories filePath = listDirectory filePath
                      >>= filterM (doesDirectoryExist . (filePath </>))

NOTE: Your version of the function will return the input filepath prepended to every output directory in the list. While this might be what you want, the version of getDirectories I am giving you may be more general as it behaves exactly like listDirectory and simply prunes the files/executables.

EDIT: Changed the import from System.FilePath.Posix to System.FilePath for true platform independence. Thanks to Justin Raymond for the suggestion.

Upvotes: 8

Justin Raymond
Justin Raymond

Reputation: 3568

All you need is System.Directory.

import Control.Monad (filterM)
import System.Directory (doesDirectoryExist, getCurrentDirectory, getDirectoryContents)

listDirs :: IO [FilePath]
listDirs = getCurrentDirectory >>= getDirectoryContents >>= filterM doesDirectoryExist

If you want to pass the filepath as argument, just doen't use getCurrentDirectory.

import Control.Monad (filterM)
import System.Directory (doesDirectoryExist, getCurrentDirectory)

listDirs :: FilePath -> IO [FilePath]
listDirs path = getDirectoryContents path >>= filterM (doesDirectoryExist . (++) path)

Upvotes: 4

Related Questions