Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding the result of a system command to a variable in Haskell

Tags:

haskell

system

How does one run a system command in Haskell and bind it's result (i.e., standard output) to a variable? In pseudo-haskell I'm looking for something like the following:

import System.Process

main = do output <- callCommand "echo hi"
          putStrLn output -- result: "hi"

This does not work. Is there something similar that does?

like image 904
George Avatar asked May 09 '16 04:05

George


2 Answers

Here is some working code:

import System.Process

main :: IO ()
main = do
  let stdin' = ""
  (errCode, stdout', stderr') <- readProcessWithExitCode "echo" ["hi"] stdin'
  putStrLn $ "stdout: " ++ stdout'
  putStrLn $ "stderr: " ++ stderr'
  putStrLn $ "errCode: " ++ show errCode

As Carsten notes, you can use readProcess, but I prefer this version because with any serious usage, you will soon be very confused as to why your command is silently failing (if you run in the command line, both stdout and stderr are, of course, shown).

like image 66
jamshidh Avatar answered Nov 15 '22 07:11

jamshidh


Expanding on jamshidh's answer, if instead of getting stdout and stderr as String you want to get them as ByteString or Text, you can use the process-extras package.

You can also use my process-streaming package:

$ import System.Process.Streaming
$ execute (piped (shell "echo foo")) (liftA3 (,,) (foldOut intoLazyBytes)    
                                                  (foldErr intoLazyBytes)
                                                  exitCode)
("foo\n","",ExitSuccess)

Also for Text:

$ import System.Process.Streaming.Text
$ execute (piped (shell "echo foo")) (liftA3 (,,) (foldOut (transduce1 utf8x intoLazyText)) 
                                                  (foldErr (transduce1 utf8x intoLazyText)) 
                                                  exitCode)
("foo\n","",ExitSuccess)
like image 37
danidiaz Avatar answered Nov 15 '22 06:11

danidiaz