Shell programming, Haskell-style

Version on this page:1.6.2@rev:2
LTS Haskell 22.29:1.6.2@rev:3
Stackage Nightly 2024-07-20:1.6.2@rev:3
Latest on Hackage:1.6.2@rev:3

See all snapshots turtle appears in

BSD-3-Clause licensed by Gabriella Gonzalez
Maintained by [email protected]
This version can be pinned in stack with:turtle-1.6.2@sha256:5691769178d8b2d0023ba289b755e03dfdf33e75fd24462e23dd02ecb7585692,5767

turtle is a reimplementation of the Unix command line environment in Haskell so that you can use Haskell as both a shell and a scripting language.

Features include:

  • Batteries included: Command an extended suite of predefined utilities

  • Interoperability: You can still run external shell commands

  • Portability: Works on Windows, OS X, and Linux

  • Exception safety: Safely acquire and release resources

  • Streaming: Transform or fold command output in constant space

  • Patterns: Use typed regular expressions that can parse structured values

  • Formatting: Type-safe printf-style text formatting

  • Modern: Supports text

Read Turtle.Tutorial for a detailed tutorial or Turtle.Prelude for a quick-start guide

turtle is designed to be beginner-friendly, but as a result lacks certain features, like tracing commands. If you feel comfortable using turtle then you should also check out the Shelly library which provides similar functionality.




  • BUG FIX: Fix turtle to build on Windows
  • BUG FIX: stripPrefix and commonPrefix now correctly handle files with extensions
    • For example, before this fix stripPrefix "./" "./foo.bar" would return Just "foo/.bar"


  • BREAKING CHANGE: Switch to the FilePath type from base instead of system-filepath
    • This is a breaking change for a couple of reasons:
      • The FilePath type has changed, so the API is not backwards-compatible
        • The thing most likely to break is if you directly imported utilities from the system-filepath or system-fileio packages to operate on turtle’s FilePaths
          • If that happens, you should first check if the Turtle module exports a utility of the same name. If so, then switch to that
          • If there is no equivalent substitute from the Turtle module then you will have to change your code to use the closest equivalent utility from the filepath or directory package
          • If you were previously using any of the system-filepath or system-fileio utilities re-exported from the Turtle module then those utilities will not break as they have been replaced with versions compatible with the FilePath type from base
        • The second thing most likely to break is any code that relies on typeclasses since because if you defined any instances for the FilePath type exported by turtle then those instances will now overlap with any instances defined for the String type
        • The conversion utilities (e.g. toText, encodeString) will still work, so code that used those conversion utilities should be less affected by this change
      • The behavior of the collapse utility is subtly different
        • collapse no longer interprets .. in paths
        • This new behavior is more correct in the presence of symlinks, so the change is (hopefully) an improvement to downstream code
    • The new API strives to match the old behavior as closely as possible
      • … so this should (hopefully) not break too much code in practice
      • With the exception of the collapse function the new API should be bug-for-bug compatible with the old API
        • Most of the surprising behavior inherited from the old API is around how . and .. are handled in paths
          • parent ".." == "." is an example of such surprising behavior
      • At some point in the future we may fix bugs in these utilities inherited from system-filepath / system-fileio, but no decision either way has been made, yet
    • Some old utilities are marked DEPRECATED if their behavior exactly matches the behavior of an existing utility from the filepath or directory package
      • These may be eventually removed at some point in the future or they remain in a deprecated state indefinitely. No decision either way has been made
      • The Turtle module also re-exports any utility suggested by a DEPRECATED pragma as a convenience
    • Other utilities are not deprecated if the old behavior significantly departs from any existing utility from the filepath or directory package
      • For example, the behavior of the filename utility differs from the behavior of System.FilePath.takeFileName for filenames that begin with a ., so we have to preserve the old behavior to avoid breaking downstream code
      • At some point in the future utilities like these may be deprecated in favor of their closest analogs in the filepath / directory packages or they may be supported indefinitely. No decision either way has been made
    • If you want to try to author code that is compatible with both the pre-1.6 and post-1.6 API:
      • If you add any instances to the FilePath type, import it qualified directly from the system-filepath package and use it only for instances
      • Otherwise, don’t import anything else from the system-filepath / system-fileio packages if you can help it. Instead, restrict yourself entirely to the utilities and FilePath type exported by the Turtle module
      • Use the conversion utilities (e.g. encodeStrings, even if they are not necessary post-1.6)
      • If that’s still not enough, use CPP and good luck!


  • Build against latest version of Win32 package


  • Expose Format constructor


  • Add fromIO utility
  • Build against GHC 9.0 / 9.2


  • Add new update utility
  • Improve documentation for limit


  • Build against optparse-applicative-


  • Build against doctest-0.17
  • Only depend on semigroups for GHC < 8.0


  • Add pattern synonyms for Size


  • Fix space leak


  • Add optionsExt: Extended version of options with header, footer, porgram-description and version information in --help flag
  • Add readlink


  • Add cptreeL


  • Add toLines
  • Add Turtle.Bytes.{fromUTF8,toUTF8}
  • Add Turtle.Bytes.{compress,decompress}
  • Always expose a MonadFail instance, relying on the fail package where needed. Related GHC 8.8 preparedness.




  • Increase upper bound on containers



  • Increase upper bound on doctest and criterion


  • Add symlink



  • Increase upper bound on doctest


  • Increase upper bound on exceptions


  • Increase upper bound on criterion


  • Increase upper bound on exceptions


  • Increase upper bound on doctest


  • Increase upper bound on async


  • GHC 8.4 support
  • Re-export encodeString/decodeString
  • Update tutorial to use stack script
  • Increase upper bounds on dependencies


  • BREAKING CHANGE: Add MonadCatch instance for Shell
    • This requires a breaking change to the internal implementation of Shell
    • Most breaking changes can be fixed by replacing the Shell constructor with the newly added _Shell utility for ease of migration
    • If you don’t use the Shell constructor then this change likely does not affect you
  • Add eprintf


  • Add grepText, uniq, nub, sort to Turtle.Prelude
  • Increase upper bound on unix-compat


  • Fix small mistake in tutorial


  • Increase upper bound on doctest


  • Add sed{Prefix,Suffix,Entire} and inplace{Prefix,Suffix,Entire}


  • Increase upper bound on doctest


  • BREAKING CHANGE: Remove unnecessary Maybe from type of single
  • BREAKING CHANGE: Consolidate searchable and executable
  • stream{,WithErr} now throws an ExitCode on failure


  • Build against ghc-8.2
  • Relax upper bound on optparse-applicative and foldl


  • Increase upper bound on foldl


  • Bug fix: cptree now correctly copies files instead of creating directories of the same name
  • Increase upper bound on criterion


  • Bug fix: Change textToLines to behave like Data.Text.splitOn "\n" instead of Data.Text.unlines
    • This fixes weird behavior around handling empty strings. splitOn does the right thing, but unlines does not. For example, this indirectly fixes a regression in sed, which would discard empty lines
  • Bug fix: which/whichAll now behave correctly on Windows
  • Add new cptree/single utilities
  • Documentation fixes


  • Fix bugs in subprocess management
  • Generalize type of repr to return any type that implements IsString
  • Add optLine, argLine, and l utilities to simplify working with Lines


  • find no longer follows symlinks
  • Increase upper bound on directory


  • BREAKING CHANGE: Several utilities now produce and consume Lines instead of Text
    • The purpose of this change is to fix a very common source of confusion for new users about which utilities are line-aware
    • Most of the impact on existing code is just changing the types by replacing Text with Line in the right places. The change at the term level should be small (based on the changes to the tutorial examples)
  • BREAKING CHANGE: Description now wraps a Doc instead of Text
    • In the most common case where users use string literals this has no effect
  • New Turtle.Bytes module that provides ByteString variations on subprocess runners
  • Fix du reporting incorrect sizes for directories
  • Add pushd, stat, lstat, which, procStrictWithErr, shellStrictWithErr, onFiles, header, subcommandGroup, and parallel
  • Backport need to GHC 7.6.3
  • Fix missing help text for option parsers
  • Fix bugs in subprocess management


  • Increase upper bound on time and transformers
  • Fix incorrect lower bound for base


  • Increase upper bound on clock dependency


  • Generalize several types to use MonadManaged
  • Generalize type of printf to use MonadIO
  • Add system, and copymod
  • Fix rmtree to more accurately match behavior of rm -r


  • Add printf, utc, procs, and shells


  • Generalize type of d format specifier to format any Integral type
  • Add inprocWithErr, inShellWithErr, inplace, and sz


  • Add subcommand and testpath
  • Use line buffering for Text-based subprocesses


  • Re-export with
  • Add begins, ends, contains, lowerBounded, mktempfile, nl, paste endless, lsif, and cut
  • Fix subprocess management bugs


  • Fix subprocess management bugs


  • BREAKING CHANGE: du now returns a Size instead of an Integer
  • New Turtle.Options module that provides convenient utilities for options parsing
  • Add hostname, outhandle, stderr, cache, countChars, countWords, and countLines
  • Fix subprocess management bugs


  • Add bounded, upperBounded, procStrict, shellStrict, arguments
  • Add several Permissions-related commands
  • Generalize several types to MonadIO


  • BREAKING CHANGE: Remove Floating/Fractional instances for Pattern and Shell
  • BREAKING CHANGE: Change behavior of Num instance for Pattern and Shell
  • Re-export (&)
  • Add asciiCI, (.||.), (.&&.), strict


  • Add fp format specifier
  • Add chars/chars high-efficiency parsing primitives
  • Fix bugs in path handling


  • Generalize type of die
  • Fix doctest


  • Initial release