import Control.Monad import Data.Digest.MD5 (hash) import Data.Word import List (sort) import Prelude import System.Directory import System.FilePath import Text.Printf (printf) import qualified Data.ByteString as BS main :: IO () main = putStr . unlines =<< getList "." getList :: FilePath -> IO [String] getList p = mapM getFileLine =<< getRecursiveContents p where getFileLine path = liftM (\c -> (hex (hash (BS.unpack c))) ++ " " ++ path) (BS.readFile path) hex :: [Word8] -> String hex = concatMap (\x -> printf "%0.2x" (toInteger x)) getRecursiveContents :: FilePath -> IO [FilePath] getRecursiveContents topdir = do names <- getDirectoryContents topdir let properNames = filter (`notElem` [".", ".."]) names paths <- concatForM properNames $ \name -> do let path = topdir name isDirectory <- doesDirectoryExist path if isDirectory then getRecursiveContents path else do isFile <- doesFileExist path if isFile then return [path] else return [] return (sort paths) concatForM :: (Monad m) => [a1] -> (a1 -> m [a]) -> m [a] concatForM xs f = liftM concat (forM xs f)