[Haskell] Re: Reading a directory tree

Peter Simons simons at cryp.to
Tue Jun 22 06:33:00 EDT 2004


Tom Hofte writes:

 > I'm looking for a way to iteratively read all the files
 > in a directory and its subdirectories, given the filepath
 > of the top-level dir.

Hope this helps:

\begin{code}
module ReadDirHier
    ( Entry(..)
    , name
    , readDirHier
    ) where

import System.Directory (getDirectoryContents, doesDirectoryExist)
import Data.List (isPrefixOf, sort)

data Entry		= Dir  FilePath [Entry]
			| File FilePath

name			:: Entry -> FilePath
name (Dir p _)		= p
name (File p)		= p

-- |Read the complete directory hierarchy starting at 'FilePath' and
-- return a tree representing it. The top-most 'Entry' will -
-- obviously - be a 'Dir'. Directories contain their sub-entries in
-- alphabetic order. The returned tree starts with the 'name' \"@.@\"
-- - /not/ with the given 'FilePath'. All file names are relative to
-- their current directory.
--
-- The function may throw exceptions when I/O fails.

readDirHier		:: FilePath -> IO Entry
readDirHier path	= readDirHier' path "."

readDirHier'		:: FilePath -> FilePath -> IO Entry
readDirHier' pre p	= do files   <- getDirectoryContents $ pre ++ "/" ++ p
			     entries <- mapM toEntry $ sort $ clean files
			     return (Dir p entries)
    where
    toEntry x   = do isDir <- doesDirectoryExist $ path ++ "/" ++ x
                     if isDir then readDirHier' path x
                              else return (File x)
                  where path = pre ++ "/" ++ p

    clean xs    = [ x | x <- xs, x /= "."     -- TODO: This should really be a
                               , x /= ".."    -- function provided by the caller.
                               , x /= "CVS"
                               , not (".#" `isPrefixOf` x)
                  ]
\end{code}



More information about the Haskell mailing list