summaryrefslogtreecommitdiff
path: root/hs/src/Files.hs
diff options
context:
space:
mode:
Diffstat (limited to 'hs/src/Files.hs')
-rw-r--r--hs/src/Files.hs65
1 files changed, 65 insertions, 0 deletions
diff --git a/hs/src/Files.hs b/hs/src/Files.hs
new file mode 100644
index 0000000..20554c1
--- /dev/null
+++ b/hs/src/Files.hs
@@ -0,0 +1,65 @@
+module Files
+( mkdirP
+, fileTree
+, isFiletype
+, copyFiles
+) where
+
+import System.Directory hiding (isSymbolicLink)
+import System.Posix.Files
+ ( FileStatus
+ , getFileStatus
+ , isBlockDevice
+ , isCharacterDevice
+ , isDirectory
+ , isNamedPipe
+ , isRegularFile
+ , isSocket
+ , isSymbolicLink
+ )
+import System.FilePath
+ ( joinPath
+ , takeExtension
+ , (</>)
+ )
+
+mkdirP = createDirectoryIfMissing True
+
+fmt :: FileStatus -> String
+fmt st | isBlockDevice st = "block"
+ | isCharacterDevice st = "char"
+ | isNamedPipe st = "pipe"
+ | isRegularFile st = "regular"
+ | isDirectory st = "directory"
+ | isSymbolicLink st = "symlink"
+ | isSocket st = "socket"
+ | otherwise = "UNKNOWN"
+
+instance Show FileStatus where
+ show st = fmt st
+
+fileTree :: [FilePath] -> IO [(FileStatus, [FilePath])]
+fileTree base = do
+ items <- listDirectory (joinPath base)
+ concat <$>
+ mapM (\entry -> do
+ let here = base <> [entry]
+ let path = joinPath here
+ st <- getFileStatus path
+ let d = (st, here)
+ if isDirectory st
+ then (d :) <$> fileTree here
+ else return [ d ]
+ ) items
+
+isFiletype :: String -> FileStatus -> [FilePath] -> Bool
+isFiletype extension st path
+ = isRegularFile st && (takeExtension . last $ path) == ('.' : extension)
+
+copyFile' :: FilePath -> FileStatus -> [FilePath] -> IO ()
+copyFile' dest st path
+ | isDirectory st = createDirectoryIfMissing True (dest </> (joinPath $ tail path))
+ | otherwise = copyFile (joinPath path) $ dest </> (joinPath $ tail path)
+
+copyFiles :: FilePath -> [(FileStatus, [FilePath])] -> IO ()
+copyFiles dest = mapM_ (uncurry $ copyFile' dest)