import Control.Monad
import Data.Digest.MD5 (hash)
import Data.Word
import List (sort)
import Prelude
import System.Directory
import System.FilePath
import System.IO
import Text.Printf (printf)
import qualified Data.ByteString.Lazy as BS
main :: IO ()
main = putStr . unlines =<< getList "."
getList :: FilePath -> IO [String]
getList p =
let getFileLine path = liftM (\c -> (hex c) ++ " " ++ path) (getFileHash path)
in mapM getFileLine =<< getRecursiveContents p
hex :: [Word8] -> String
hex = concatMap (\x -> printf "%0.2x" (toInteger x))
getFileHash :: FilePath -> IO [Word8]
getFileHash path = do
handle <- openFile path ReadMode
contents <- BS.hGetContents handle
let !hashed = hash $ BS.unpack contents
hClose handle
return hashed
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)