shell-conduit-3.0: Write shell scripts with Conduit

Safe HaskellNone
LanguageHaskell98

Data.Conduit.Shell

Contents

Description

Shell scripting with Conduit

This module consists only of re-exports, including a few thousand top-level names based on PATH. If you don't want that, you can cherry-pick specific modules to import from the library.

See Data.Conduit.Shell.PATH for all binaries. But you should be able to use whatever executables are in your PATH when the library is compiled.

Examples

The monad instance of Conduit will simply pass along all stdout results:

>>> run (do echo "Hello"; sed "s/l/a/"; echo "OK!")
Hello
OK!

Piping with Conduit's normal pipe will predictably pipe things together, as in Bash:

>>> run (do shell "echo Hello" $= sed "s/l/a/"; echo "OK!")
Healo
OK!

Streaming pipes (aka lazy pipes) is also possible:

>>> run (do tail' "foo.txt" "-f" $= grep "--line-buffered" "Hello")
Hello, world!
Oh, hello!

(Remember that grep needs --line-buffered if it is to output things line-by-line).

How it works

All executable names in the PATH at compile-time are brought into scope as runnable process conduits e.g. ls or grep.

Stdin/out and stderr are handled as an Either type: Chunk

Left is stderr, Right is stdin/stdout.

All processes are bound as variadic process calling functions, like this:

rmdir :: ProcessType r => r
ls :: ProcessType r => r

But ultimately the types end up being:

rmdir "foo" :: Conduit Chunk m Chunk
ls :: Conduit Chunk m Chunk
ls "." :: Conduit Chunk m Chunk

Etc.

Run all shell scripts with run:

run :: (MonadIO m, MonadBaseControl IO m)
    => Conduit Chunk (ShellT m) Chunk -> m ()

String types

If using OverloadedStrings so that you can use Text for arguments, then also enable ExtendedDefaultRules, otherwise you'll get ambiguous type errors.

{--}

But this isn't necessary if you don't need to use Text yet. Strings literals will be interpreted as String. Though you can pass a value of type Text or any instance of CmdArg without needing conversions.

Synopsis

Running scripts

run :: (MonadIO m, MonadBaseControl IO m) => Conduit Chunk (ShellT m) Chunk -> m () Source

Run a shell scripting conduit.

Running custom processes

shell :: MonadResource m => String -> Conduit Chunk m Chunk Source

Run a shell command.

proc :: MonadResource m => String -> [String] -> Conduit Chunk m Chunk Source

Run a shell command.

I/O chunks

bytes :: Monad m => Conduit Chunk m ByteString Source

Extract the stdout values from the stream, discarding any errors.

unbytes :: Monad m => Conduit ByteString m Chunk Source

Extract the stdout values from the stream, discarding any errors.

withRights :: Monad m => Conduit ByteString m ByteString -> Conduit Chunk m Chunk Source

Do something with just the rights.

redirect :: Monad m => ChunkType -> Conduit Chunk m Chunk Source

Redirect the given chunk type to the other type.

quiet :: (Monad m, MonadIO m) => Conduit Chunk m Chunk -> Conduit Chunk m Chunk Source

Discard any output from the command: make it quiet.

writeChunks :: MonadIO m => Consumer Chunk m () Source

Write chunks to stdout and stderr.

discardChunks :: MonadIO m => Consumer Chunk m () Source

Discard all chunks.

Re-exports

The following modules are exported for scripting convenience. Data.Conduit and Data.Conduit.Filesystem are re-exported from other libraries because they are typical uses. If you want a stream of the contents of a directory, recursively, sourceDirectoryDeep is handy. A program like find is strict, whereas a Conduit can stop processing whenever you wish.

You might want to import the regular Conduit modules qualified, too:

import qualified Data.Conduit.List as CL

Which contains handy functions for working on streams in a list-like way. See the rest of the handy modules for Conduit in conduit-extra: http://hackage.haskell.org/package/conduit-extra

Also of interest is csv-conduit: http://hackage.haskell.org/package/csv-conduit And html-conduit: http://hackage.haskell.org/package/html-conduit And http-conduit: http://hackage.haskell.org/package/http-conduit

Finally, see the Conduit category on Hackage for other useful libraries: http://hackage.haskell.org/packages/#cat:Conduit

All of these general purpose Conduits can be used in shell scripting.