Use operating system (OS) commands in Haskell programs as if they were native Haskell functions, by treating their inputs and outputs as Haskell streams. This allows you to write high-level Haskell scripts that can perform tasks similar to shell scripts, but with C-like performance, and with strong safety guarantees, refactorability, and modularity.
Use the following imports in the examples below:
>>>:set -XFlexibleContexts>>>:set -XScopedTypeVariables>>>:set -XQuasiQuotes>>> import Data.Function ((&))
>>> import Streamly.Unicode.String (str)
>>> import qualified Streamly.Data.Array as Array>>> import qualified Streamly.Console.Stdio as Stdio>>> import qualified Streamly.Data.Fold as Fold>>> import qualified Streamly.Data.Stream.Prelude as Stream>>> import qualified Streamly.System.Command as Command>>> import qualified Streamly.Internal.FileSystem.Dir as DirThe shell command echo "hello world" | tr [a-z] [A-Z] can be written as
follows using this package:
>>>:{
Command.toBytes [str|echo "hello world"|] -- Stream IO Word8&Command.pipeBytes [str|tr [a-z] [A-Z]|] -- Stream IO Word8&Stream.fold Stdio.write -- IO ():}
HELLOWORLDIf you want to execute the same command using the shell pipe syntax:
>>>:{
Command.toBytes [str|sh "-c" "echo 'hello world' | tr [a-z] [A-Z]"|] -- Stream IO Word8&Stream.fold Stdio.write -- IO ():}
HELLOWORLDYou can run commands concurrently by using streamly's concurrent combinators.
Running @grep@ concurrently on many files:
>>>:{
grep file =Command.toBytes [str|grep -H "pattern" #{file}|] -- Stream IO Word8&Stream.handle (\(_ ::Command.ProcessFailure) ->Stream.nil) -- Stream IO Word8&Stream.foldMany (Fold.takeEndBy (==10) Array.write) -- Stream IO (Array Word8):}
>>>:{
pgrep =Dir.readFiles "."-- Stream IO FilePath&Stream.parConcatMap id grep -- Stream IO (Array Word8)&Stream.fold Stdio.writeChunks -- IO ():}Please visit Streamly homepage for more details about streamly.
Available under Apache-2.0 license.