FileManip, an expressive Haskell library for manipulating files

I just released version 0.1 of FileManip, a Haskell library I put together to make it easier to futz about with files in the filesystem.

There are a few different components to the package.

The Find module lets you search the filesystem for files, after the manner of the Unix find program. It provides a nice embedded language for building filters and controlling recursion, so you can write readable expressions like this:

find always (fileType ==? RegularFile &&? extension ==? ".hs") "myPath"

This will return a list of all Haskell source files under myPath. The list is built lazily, so if you have a million files in your tree, but you only examine the first ten elements of the list, no extra work is done.

The obvious counterparts to the Find module in other languages would be Perl’s File::Find module, and Python’s os.walk function.

The Manip module provides some handy functions for manipulating files. For example, renameWith provides procedural renaming: given a file name, it applies a function to it, then renames the file to that name. Here’s how you might use it to change your naming convention for C++ source files:

find always (extension ==? ".cpp") >>=
    mapM_ (renameWith (replaceExtension "C"))

The modifyInPlace and modifyWithBackup functions edit a file in place (the latter saves the original copy to a procedurally-renamed backup file), so that you can more easily write sed-like expressions:

modifyInPlace (map toUpper) "shouting.txt"

Least interesting, but nonetheless useful, is GlobPattern, a glob pattern matching module. I wrote this because Haskell doesn’t provide a standard one, and the only other one I know of (in the MissingH library) goes through the regexp machinery. Ew.

Online docs are published here. The source tarball is available here, at HackageDB, the Haskell package database. There’s also a Darcs repository available here:

darcs get


Posted in haskell, open source
2 comments on “FileManip, an expressive Haskell library for manipulating files
  1. Linus says:

    I wrote a basic function, like this:

    listFiles :: FilePath -> IO [FilePath]
    listFiles fpath = find always (fileType ==? RegularFile &&? extension ~~? “*.(JPEG|MOV)”) fpath

    and it hangs forever at 100% CPU usage…

    I know I’m doing something wrong here — please help.

  2. John Wiegley says:

    I’ve created find-conduit ( as another way of doing efficient filesystem traversals, whose results feed into a conduit. It supports prune directory trees and makes it very easy to write new predicates.

Leave a Reply

Your email address will not be published. Required fields are marked *