HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Moduleturtle-1.6.2Haskell2010

Turtle.Prelude

This module provides a large suite of utilities that resemble Unix utilities.

Many of these commands are just existing Haskell commands renamed to match their Unix counterparts:

Example3 expressions
:set -XOverloadedStringscd "/tmp"pwdFilePath "/tmp"

Some commands are Shells that emit streams of values. view prints all values in a Shell stream:

Example2 expressions
view (ls "/usr")FilePath "/usr/lib"FilePath "/usr/src"FilePath "/usr/sbin"FilePath "/usr/include"FilePath "/usr/share"FilePath "/usr/games"FilePath "/usr/local"FilePath "/usr/bin"view (find (suffix "Browser.py") "/usr/lib")FilePath "/usr/lib/python3.4/idlelib/ClassBrowser.py"FilePath "/usr/lib/python3.4/idlelib/RemoteObjectBrowser.py"FilePath "/usr/lib/python3.4/idlelib/PathBrowser.py"FilePath "/usr/lib/python3.4/idlelib/ObjectBrowser.py"

Use fold to reduce the output of a Shell stream:

Example3 expressions
import qualified Control.Foldl as Foldfold (ls "/usr") Fold.length8fold (find (suffix "Browser.py") "/usr/lib") Fold.headJust (FilePath "/usr/lib/python3.4/idlelib/ClassBrowser.py")

Create files using output:

Example2 expressions
output "foo.txt" ("123" <|> "456" <|> "ABC")realpath "foo.txt"FilePath "/tmp/foo.txt"

Read in files using input:

Example1 expression
stdout (input "foo.txt")123456ABC

Format strings in a type safe way using format:

Example2 expressions
dir <- pwdformat ("I am in the "%fp%" directory") dir"I am in the /tmp directory"

Commands like grep, sed and find accept arbitrary Patterns

Example3 expressions
stdout (grep ("123" <|> "ABC") (input "foo.txt"))123ABClet exclaim = fmap (<> "!") (plus digit)stdout (sed exclaim (input "foo.txt"))123!456!ABC

Note that grep and find differ from their Unix counterparts by requiring that the Pattern matches the entire line or file name by default. However, you can optionally match the prefix, suffix, or interior of a line:

Example3 expressions
stdout (grep (has    "2") (input "foo.txt"))123stdout (grep (prefix "1") (input "foo.txt"))123stdout (grep (suffix "3") (input "foo.txt"))123

You can also build up more sophisticated Shell programs using sh in conjunction with do notation:

{-# LANGUAGE OverloadedStrings #-}

import Turtle

main = sh example

example = do
    -- Read in file names from "files1.txt" and "files2.txt"
    file <- fmap fromText (input "files1.txt" <|> input "files2.txt")

    -- Stream each file to standard output only if the file exists
    True <- liftIO (testfile file)
    line <- input file
    liftIO (echo line)

See Turtle.Tutorial for an extended tutorial explaining how to use this library in greater detail.

  • 6 types
  • 162 values
  • Packageturtle-1.6.2
  • Exports177
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourcePrelude.hs

IO

41 declarations
valueecho :: MonadIO io => Line -> io ()
#

Print exactly one line to stdout

To print more than one line see printf, which also supports formatted output

valueerr :: MonadIO io => Line -> io ()
#

Print exactly one line to stderr

valueexport :: MonadIO io => Text -> Text -> io ()
#

Set or modify an environment variable

Note: This will change the current environment for all of your program's threads since this modifies the global state of the process

valuecd :: MonadIO io => FilePath -> io ()
#

Change the current directory

Note: This will change the current directory for all of your program's threads since this modifies the global state of the process

valuemv :: MonadIO io => FilePath -> FilePath -> io ()
#

Move a file or directory

Works if the two paths are on the same filesystem. If not, mv will still work when dealing with a regular file, but the operation will not be atomic

valuemktree :: MonadIO io => FilePath -> io ()
#

Create a directory tree (equivalent to mkdir -p)

Does not fail if the directory is present

valuermtree :: MonadIO io => FilePath -> io ()
#

Remove a directory tree (equivalent to rm -r)

Use at your own risk

valuetouch :: MonadIO io => FilePath -> io ()
#

Touch a file, updating the access and modification times to the current time

Creates an empty file if it does not exist

valuetime :: MonadIO io => io a -> io (a, NominalDiffTime)
#

Time how long a command takes in monotonic wall clock time

Returns the duration alongside the return value

valuesleep :: MonadIO io => NominalDiffTime -> io ()
#

Sleep for the given duration

A numeric literal argument is interpreted as seconds. In other words, (sleep 2.0) will sleep for two seconds.

valueexit :: MonadIO io => ExitCode -> io a
#

Exit with the given exit code

An exit code of 0 indicates success

Managed

9 declarations
valuemktemp
  1. :: MonadManaged managed
  2. => FilePath

    Parent directory

  3. -> Text

    File name template

  4. -> managed (FilePath, Handle)
#

Create a temporary file underneath the given directory

Deletes the temporary file when done

Note that this provides the Handle of the file in order to avoid a potential race condition from the file being moved or deleted before you have a chance to open the file. The mktempfile function provides a simpler API if you don't need to worry about that possibility.

valuemktempdir
  1. :: MonadManaged managed
  2. => FilePath

    Parent directory

  3. -> Text

    Directory name template

  4. -> managed FilePath
#

Create a temporary directory underneath the given directory

Deletes the temporary directory when done

valuepushd :: MonadManaged managed => FilePath -> managed ()
#

Change the current directory. Once the current Shell is done, it returns back to the original directory.

Example4 expressions
:set -XOverloadedStringscd "/"view (pushd "/tmp" >> pwd)FilePath "/tmp"pwdFilePath "/"

Shell

46 declarations
valuelsif :: (FilePath -> IO Bool) -> FilePath -> Shell FilePath
#

Stream all recursive descendents of the given directory

This skips any directories that fail the supplied predicate

lstree = lsif (\_ -> return True)
valuesed :: Pattern Text -> Shell Line -> Shell Line
#

Replace all occurrences of a Pattern with its Text result

sed performs substitution on a line-by-line basis, meaning that substitutions may not span multiple lines. Additionally, substitutions may occur multiple times within the same line, like the behavior of s/.../.../g.

Warning: Do not use a Pattern that matches the empty string, since it will match an infinite number of times. sed tries to detect such Patterns and die with an error message if they occur, but this detection is necessarily incomplete.

valuepaste :: Shell a -> Shell b -> Shell (a, b)
#

Merge two Shells together, element-wise

If one Shell is longer than the other, the excess elements are truncated

valuelimit :: Int -> Shell a -> Shell a
#

Limit a Shell to a fixed number of values

NOTE: This is not lazy and will still consume the entire input stream. There is no way to implement a lazy version of this utility.

valuelimitWhile :: (a -> Bool) -> Shell a -> Shell a
#

Limit a Shell to values that satisfy the predicate

This terminates the stream on the first value that does not satisfy the predicate

valuecache :: (Read a, Show a) => FilePath -> Shell a -> Shell a
#

Cache a Shell's output so that repeated runs of the script will reuse the result of previous runs. You must supply a FilePath where the cached result will be stored.

The stored result is only reused if the Shell successfully ran to completion without any exceptions. Note: on some platforms Ctrl-C will flush standard input and signal end of file before killing the program, which may trick the program into "successfully" completing.

valueparallel :: [IO a] -> Shell a
#

Run a list of IO actions in parallel using fork and wait.

Example1 expression
view (parallel [(sleep 3) >> date, date, date])2016-12-01 17:22:10.83296 UTC2016-12-01 17:22:07.829876 UTC2016-12-01 17:22:07.829963 UTC
valuesingle :: MonadIO io => Shell a -> io a
#

Returns the result of a Shell that outputs a single line. Note that if no lines / more than 1 line is produced by the Shell, this function will die with an error message.

main = do
  directory <- single (inshell "pwd" empty)
  print directory
valueuniq :: Eq a => Shell a -> Shell a
#

Filter adjacent duplicate elements:

Example1 expression
view (uniq (select [1,1,2,1,3]))1213
valueuniqOn :: Eq b => (a -> b) -> Shell a -> Shell a
#

Filter adjacent duplicates determined after applying the function to the element:

Example1 expression
view (uniqOn fst (select [(1,'a'),(1,'b'),(2,'c'),(1,'d'),(3,'e')]))(1,'a')(2,'c')(1,'d')(3,'e')
valueuniqBy :: (a -> a -> Bool) -> Shell a -> Shell a
#

Filter adjacent duplicate elements determined via the given function:

Example1 expression
view (uniqBy (==) (select [1,1,2,1,3]))1213
valuenub :: Ord a => Shell a -> Shell a
#

Return a new Shell that discards duplicates from the input Shell:

Example1 expression
view (nub (select [1, 1, 2, 3, 3, 4, 3]))1234
valuenubOn :: Ord b => (a -> b) -> Shell a -> Shell a
#

Return a new Shell that discards duplicates determined via the given function from the input Shell:

Example1 expression
view (nubOn id (select [1, 1, 2, 3, 3, 4, 3]))1234
valuesort :: (Functor io, MonadIO io, Ord a) => Shell a -> io [a]
#

Return a list of the sorted elements of the given Shell, keeping duplicates:

Example1 expression
sort (select [1,4,2,3,3,7])[1,2,3,3,4,7]
valuesortOn :: (Functor io, MonadIO io, Ord b) => (a -> b) -> Shell a -> io [a]
#

Return a list of the elements of the given Shell, sorted after applying the given function and keeping duplicates:

Example1 expression
sortOn id (select [1,4,2,3,3,7])[1,2,3,3,4,7]
valuesortBy
  1. :: (Functor io, MonadIO io)
  2. => a -> a -> Ordering
  3. -> Shell a
  4. -> io [a]
#

Return a list of the elements of the given Shell, sorted by the given function and keeping duplicates:

Example1 expression
sortBy (comparing fst) (select [(1,'a'),(4,'b'),(2,'c'),(3,'d'),(3,'e'),(7,'f')])[(1,'a'),(2,'c'),(3,'d'),(3,'e'),(4,'b'),(7,'f')]
valuetoLines :: Shell Text -> Shell Line
#

Group an arbitrary stream of Text into newline-delimited Lines

Example2 expressions
stdout (toLines ("ABC" <|> "DEF" <|> "GHI")ABCDEFGHIstdout (toLines empty)  -- Note that this always emits at least 1 `Line`
Example1 expression
stdout (toLines ("ABC\nDEF" <|> "" <|> "GHI\nJKL"))ABCDEFGHIJKL

Folds

3 declarations
valuecountChars :: Integral n => Fold Line n
#

Count the number of characters in the stream (like wc -c)

This uses the convention that the elements of the stream are implicitly ended by newlines that are one character wide

valuecountLines :: Integral n => Fold Line n
#

Count the number of lines in the stream (like wc -l)

This uses the convention that each element of the stream represents one line

Text

1 declaration

Subprocess management

17 declarations
valueproc
  1. :: MonadIO io
  2. => Text

    Command

  3. -> [Text]

    Arguments

  4. -> Shell Line

    Lines of standard input

  5. -> io ExitCode

    Exit code

#

Run a command using execvp, retrieving the exit code

The command inherits stdout and stderr for the current process

valueshell
  1. :: MonadIO io
  2. => Text

    Command line

  3. -> Shell Line

    Lines of standard input

  4. -> io ExitCode

    Exit code

#

Run a command line using the shell, retrieving the exit code

This command is more powerful than proc, but highly vulnerable to code injection if you template the command line with untrusted input

The command inherits stdout and stderr for the current process

valueinproc
  1. :: Text

    Command

  2. -> [Text]

    Arguments

  3. -> Shell Line

    Lines of standard input

  4. -> Shell Line

    Lines of standard output

#

Run a command using execvp, streaming stdout as lines of Text

The command inherits stderr for the current process

valueinshell
  1. :: Text

    Command line

  2. -> Shell Line

    Lines of standard input

  3. -> Shell Line

    Lines of standard output

#

Run a command line using the shell, streaming stdout as lines of Text

This command is more powerful than inproc, but highly vulnerable to code injection if you template the command line with untrusted input

The command inherits stderr for the current process

Throws an ExitCode exception if the command returns a non-zero exit code

valueinprocWithErr
  1. :: Text

    Command

  2. -> [Text]

    Arguments

  3. -> Shell Line

    Lines of standard input

  4. -> Shell (Either Line Line)

    Lines of either standard output (Right) or standard error (Left)

#

Run a command using the shell, streaming stdout and stderr as lines of Text. Lines from stdout are wrapped in Right and lines from stderr are wrapped in Left.

Throws an ExitCode exception if the command returns a non-zero exit code

valueinshellWithErr
  1. :: Text

    Command line

  2. -> Shell Line

    Lines of standard input

  3. -> Shell (Either Line Line)

    Lines of either standard output (Right) or standard error (Left)

#

Run a command line using the shell, streaming stdout and stderr as lines of Text. Lines from stdout are wrapped in Right and lines from stderr are wrapped in Left.

This command is more powerful than inprocWithErr, but highly vulnerable to code injection if you template the command line with untrusted input

Throws an ExitCode exception if the command returns a non-zero exit code

valueprocStrict
  1. :: MonadIO io
  2. => Text

    Command

  3. -> [Text]

    Arguments

  4. -> Shell Line

    Lines of standard input

  5. -> io (ExitCode, Text)

    Exit code and stdout

#

Run a command using execvp, retrieving the exit code and stdout as a non-lazy blob of Text

The command inherits stderr for the current process

valueshellStrict
  1. :: MonadIO io
  2. => Text

    Command line

  3. -> Shell Line

    Lines of standard input

  4. -> io (ExitCode, Text)

    Exit code and stdout

#

Run a command line using the shell, retrieving the exit code and stdout as a non-lazy blob of Text

This command is more powerful than proc, but highly vulnerable to code injection if you template the command line with untrusted input

The command inherits stderr for the current process

valueshellStrictWithErr
  1. :: MonadIO io
  2. => Text

    Command line

  3. -> Shell Line

    Lines of standard input

  4. -> io (ExitCode, Text, Text)

    (Exit code, stdout, stderr)

#

Run a command line using the shell, retrieving the exit code, stdout, and stderr as a non-lazy blob of Text

This command is more powerful than proc, but highly vulnerable to code injection if you template the command line with untrusted input

valuestream
  1. :: CreateProcess

    Command

  2. -> Shell Line

    Lines of standard input

  3. -> Shell Line

    Lines of standard output

#

stream generalizes inproc and inshell by allowing you to supply your own custom CreateProcess. This is for advanced users who feel comfortable using the lower-level process API

Throws an ExitCode exception if the command returns a non-zero exit code

Permissions

19 declarations
datadata Permissions
#

This type is the same as System.Directory.Permissions type except combining the executable and searchable fields into a single executable field for consistency with the Unix chmod. This simplification is still entirely consistent with the behavior of System.Directory, which treats the two fields as interchangeable.

Instances4Eq, Ord, Read, Show
valuechmod
  1. :: MonadIO io
  2. => (Permissions -> Permissions)

    Permissions update function

  3. -> FilePath

    Path

  4. -> io Permissions

    Updated permissions

#

Update a file or directory's user permissions

chmod rwo         "foo.txt"  -- chmod u=rw foo.txt
chmod executable  "foo.txt"  -- chmod u+x foo.txt
chmod nonwritable "foo.txt"  -- chmod u-w foo.txt

The meaning of each permission is:

  • readable (+r for short): For files, determines whether you can read from that file (such as with input). For directories, determines whether or not you can list the directory contents (such as with ls). Note: if a directory is not readable then ls will stream an empty list of contents

  • writable (+w for short): For files, determines whether you can write to that file (such as with output). For directories, determines whether you can create a new file underneath that directory.

  • executable (+x for short): For files, determines whether or not that file is executable (such as with proc). For directories, determines whether or not you can read or execute files underneath that directory (such as with input or proc)

File size

21 declarations
newtypenewtype Size
#

An abstract file size

Specify the units you want by using an accessor like kilobytes

The Num instance for Size interprets numeric literals as bytes

Instances4Eq, Num, Ord, Show
  • Eq SizeDefined in turtle-1.6.2 · Turtle.Prelude
  • Num SizeDefined in turtle-1.6.2 · Turtle.Prelude
  • Ord SizeDefined in turtle-1.6.2 · Turtle.Prelude
  • Show SizeDefined in turtle-1.6.2 · Turtle.Prelude
patternpattern B :: Integral n => n -> Size
#

Construct a Size from an integer in bytes

Example1 expression
format sz (B 42)"42 B"
patternpattern KB :: Integral n => n -> Size
#

Construct a Size from an integer in kilobytes

Example2 expressions
format sz (KB 42)"42.0 KB"let B n = KB 1 in n1000
patternpattern MB :: Integral n => n -> Size
#

Construct a Size from an integer in megabytes

Example2 expressions
format sz (MB 42)"42.0 MB"let KB n = MB 1 in n1000
patternpattern GB :: Integral n => n -> Size
#

Construct a Size from an integer in gigabytes

Example2 expressions
format sz (GB 42)"42.0 GB"let MB n = GB 1 in n1000
patternpattern TB :: Integral n => n -> Size
#

Construct a Size from an integer in terabytes

Example2 expressions
format sz (TB 42)"42.0 TB"let GB n = TB 1 in n1000
patternpattern KiB :: Integral n => n -> Size
#

Construct a Size from an integer in kibibytes

Example2 expressions
format sz (KiB 42)"43.8 KB"let B n = KiB 1 in n1024
patternpattern MiB :: Integral n => n -> Size
#

Construct a Size from an integer in mebibytes

Example2 expressions
format sz (MiB 42)"44.40 MB"let KiB n = MiB 1 in n1024
patternpattern GiB :: Integral n => n -> Size
#

Construct a Size from an integer in gibibytes

Example2 expressions
format sz (GiB 42)"45.97 GB"let MiB n = GiB 1 in n1024
patternpattern TiB :: Integral n => n -> Size
#

Construct a Size from an integer in tebibytes

Example2 expressions
format sz (TiB 42)"46.179 TB"let GiB n = TiB 1 in n1024
valuesz :: Format r (Size -> r)
#

Format a Size using a human readable representation

Example5 expressions
format sz 42"42 B"format sz 2309"2.309 KB"format sz 949203"949.203 KB"format sz 1600000000"1.600 GB"format sz 999999999999999999"999999.999 TB"

File status

16 declarations
newtypenewtype FileStatus
#

POSIX defines operations to get information, such as owner, permissions, size and access times, about a file. This information is represented by the FileStatus type.

Note: see chmod.

Limitations: Support for high resolution timestamps is filesystem dependent:

  • HFS+ volumes on OS X only support whole-second times.

Headers

2 declarations
datadata WithHeader a
#

Constructors

  • Header a

    The first line with the header

  • Row a a

    Every other line: 1st element is header, 2nd element is original row

Instances1Show

Exceptions

2 declarations