Script for copying files to the appropriate directory In the book Real World Haskell, the author writes in the first line of every file that uses, for example the following: file: ch05/PrettyJSON. The chapter slash and the name of a module.

I wanted to create a script which reads the first line and copies the files to the appropriate directory. In the above example we should copy the file to the directory ch05. I wanted to write this in Haskell in order to use it for "real world" applications.

But before starting writing to Haskell I wrote it in Python:

import os
import shutil

current_dir = os.getcwd()
current_files=os.listdir(current_dir)
haskell_files=filter(lambda x:x.find(".hs")!=-1,current_files)

for x in haskell_files:
 with open(x,"r") as f:
     header=f.readline()
    try:
        chIndex=header.index("ch")
    except ValueError as e:
        continue

    number=header[chIndex:chIndex+4]
 try:
    os.mkdir(number)
    shutil.copy2(x,number)
except OSError as e:
    shutil.copy2(x,number)


And then I tried to write the same code in Haskell:

f x = dropWhile (\x-&gt; x/='c') x
g x = takeWhile (\x-&gt; x=='c' || x=='h' || isDigit x) x
z= do 
   y&lt;-getCurrentDirectory
   e&lt;-getDirectoryContents y
   let b=findhs e
   mapM w b
findhs filepaths = filter (isSuffixOf ".hs") filepaths
w filename= do
           y&lt;-readFile filename
           let a=(g.f) y
           if "ch" `isPrefixOf` a
           then do
                 createDirectoryIfMissing False a
                 g&lt;-getCurrentDirectory
                 writeFile (g ++"/"++ a ++ "/" ++ filename) y
            else
                return ()
main=z


Haskell code should be more elegant and more compact but it is not. Can you give me suggestions on making the above program more Haskellish?
Notes:


don't use single letter variable names for top level bindings
leave spaces around syntax like = and &lt;-
use meaningful variable names for system values (such as file contents)
inline single uses of tiny functions, such as your findhs e
give your core algorithm, w, a meaningful name
don't use long names for local parameters like filepaths. fs is fine.
use pointfree style for arguments in the final position
use when instead of if .. then ... else return ()
use the filepath library for nice file path construction
your only use of f and g is to compose them. so do that and name the result.
use section syntax for lambdas as function arguments to HOFs
indent consistently
use mapM_ when the result you don't care about.


Resulting in:

import Data.Char
import Data.List
import Control.Monad
import System.Directory
import System.FilePath

clean = takeWhile (\x -&gt; x == 'c' || x == 'h' || isDigit x)
      . dropWhile (/='c')

process path = do
   y &lt;- readFile path

   let a = clean y

   when ("ch" `isPrefixOf` a) $ do
         createDirectoryIfMissing False a
         g &lt;- getCurrentDirectory
         writeFile (g &lt;/&gt; a &lt;/&gt; path) y

main = do
    y &lt;- getCurrentDirectory
    e &lt;- getDirectoryContents y
    mapM_ process $ filter (isSuffixOf ".hs") e