Haskell から外部コマンドを実行してみる

本物のプログラマはHaskellを使う / 第5回 ListではなくMaybeを使う意義に runInteractiveProcess関数を使った例があります。

  • runInteractiveProcessは,実行するファイルの名前とコマンドライン引数を渡し,別のプロセスでそのコマンドを実行する関数です。オプションとして,第3引数に作業ディレクトリを,第4引数に環境変数を与えることができます。
  • 第4引数は,環境変数とその値の「対(pair,ペア)」です。(Just [("HREF_DATADIR","home")])
  • 返り値は,stdin,stdout,stderrを示すハンドル(Handle)と実行したプロセスハンドル(ProcessHandle)の組です。
  • process-1.0.0.0: Process libraries
> :m + System.Process
> :m + System.IO

> (stdin, stdout, stderr, procHandle) <- runInteractiveProcess  "ls" []  Nothing Nothing

-- 標準出力への出力
> hGetContents stdout >>= putStrLn
AppData
Application Data
Contacts
(snip)
スタート メニュー

> (stdin, stdout, stderr, procHandle) <- runInteractiveProcess  "ls" ["gg"]  Nothing Nothing

-- 標準エラーへの出力
> hGetContents stderr >>= putStrLn
"ls": gg: No such file or directory

-- Process の終了ステータス
> getProcessExitCode procHandle
Just (ExitFailure 2)

> (stdin, stdout, stderr ,procHandle) <- runInteractiveProcess  "ls" []  Nothing Nothing

-- Process の終了ステータス
> getProcessExitCode procHandle
Just ExitSuccess

-- stdin へ入力してみる。
-- 以下と同等。
-- $ echo "hello" | cat  --=> hello
> (stdin, stdout, stderr ,procHandle) <- runInteractiveProcess  "cat" []  Nothing Nothing
> hPutStrLn stdin "Hello,world!"
> hFlush stdin
> hClose stdin
>  putStrLn =<< hGetLine stdout
Hello,world!

-- >  putStrLn =<< hGetContents stdout

Ticket #431 (closed bug: fixed) runInteractiveProcess and closed stdin.

> (inp,out,err,procHandle) <- runInteractiveCommand "echo \"Hello dysfunctional world!\""
>  waitForProcess procHandle
ExitSuccess
> putStrLn =<< hGetLine out
"Hello dysfunctional world!"

> (inp,out,err,procHandle) <- runInteractiveCommand "ls"
> putStrLn =<< hGetContents out
AppData
Application Data
(snip)
workspace
スタート メニュー