Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6185943
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 24, 20262026-05-24T01:48:08+00:00 2026-05-24T01:48:08+00:00

I find myself doing more and more scripting in haskell. But there are some

  • 0

I find myself doing more and more scripting in haskell. But there are some cases where I’m really not sure of how to do it “right”.
e.g. copy a directory recursively (a la unix cp -r).

Since I mostly use linux and Mac Os I usually cheat:

import System.Cmd
import System.Exit

copyDir ::  FilePath -> FilePath -> IO ExitCode
copyDir src dest = system $ "cp -r " ++ src ++ " " ++ dest

But what is the recommended way to copy a directory in a platform independent fashion?
I didn’t find anything suitable on hackage.

This is my rather naiv implementation I use so far:

import System.Directory
import System.FilePath((</>))
import Control.Applicative((<$>))
import Control.Exception(throw)
import Control.Monad(when,forM_)

copyDir ::  FilePath -> FilePath -> IO ()
copyDir src dst = do
  whenM (not <$> doesDirectoryExist src) $
    throw (userError "source does not exist")
  whenM (doesFileOrDirectoryExist dst) $
    throw (userError "destination already exists")

  createDirectory dst
  content <- getDirectoryContents src
  let xs = filter (`notElem` [".", ".."]) content
  forM_ xs $ \name -> do
    let srcPath = src </> name
    let dstPath = dst </> name
    isDirectory <- doesDirectoryExist srcPath
    if isDirectory
      then copyDir srcPath dstPath
      else copyFile srcPath dstPath

  where
    doesFileOrDirectoryExist x = orM [doesDirectoryExist x, doesFileExist x]
    orM xs = or <$> sequence xs
    whenM s r = s >>= flip when r

Any suggestions of what really is the way to do it?


I updated this with the suggestions of hammar and FUZxxl.
…but still it feels kind of clumsy to me for such a common task!

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-24T01:48:10+00:00Added an answer on May 24, 2026 at 1:48 am

    I couldn’t find anything that does this on Hackage.

    Your code looks pretty good to me. Some comments:

    1. dstExists <- doesDirectoryExist dst
      

      This does not take into account that a file with the destination name might exist.

    2. if or [not srcExists, dstExists] then print "cannot copy"
      

      You might want to throw an exception or return a status instead of printing directly from this function.

    3. paths <- forM xs $ \name -> do
          [...]
        return ()
      

      Since you’re not using paths for anything, you can change this to

      forM_ xs $ \name -> do
        [...]
      
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Not exactly sure what to call this, but in SQL I often find myself
Something I find myself doing more and more is checking a string for empty
I find myself doing the following a lot, and i don't know if there
As I develop more with vim, I find myself wanting to copy in blocks
I frequently find myself doing some analysis in R and then wanting to make
I find myself doing this repeatedy. $jq(button).filter(function(){ return this.id.match(/^user_(\d+)_edit$/); }).click(function(){ var matches = this.id.match(/^user_(\d+)_edit$/);
I often find myself doing quick checks like this: if (!eregi('.php', $fileName)) { $filename
One of the things I find myself doing often is passing string literals as
I am developing a program where I find myself doing this like this a
While using Vim (at home and at work), I often find myself doing similar

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.