Module Unix.Shell

Simple functions to interact with shell pipelines.

Shell Pipelines

Shell.input f (cmd list) is analogous to:

let cmd  = "echo" in
let list = ["black and white"] in
let chan = Unix.open_process_in (join (cmd::list))  in
let result = f chan in
Unix.close_process_in chan, result 

but the former makes sure to close the channel even if an exception is raised in f.

In addition, Shell.input is somewhat safer than Unix.open_process_in in that it quotes the components of list, thus preventing some errors and security holes due to shell metacharacters, filenames with spaces in them, and the like.

For example, compare:

Shell.output is analogous.

Pipelines of commands are also supported, and several higher-level convenience functions are built upon input and output and so inherit their properties.

Types

type cmd = string list

The type of simple shell commands.

type pipeline = private string

The type of pipelines of shell commands.

Representing Commands and Pipelines

val cmd : cmd -> pipeline

(cmd argv) makes a pipeline out of a list of strings, representing a single shell command.

The list is the argument vector representing the command, including argv0.

Examples:

  • ["echo"; "foo and (bar)"]
  • ["date"; "+%Y-%m-%d"]
  • ["cat"; "foo"; "bar"; "baz"]
val pipeline : cmd list -> pipeline

(pipeline argvs) makes a pipeline out of a list of shell commands.

For example:

  • [["cat";"/etc/passwd"]; ["wc";"-l"]] represents:
  • "cat /etc/passwd | wc -l"

Input: Reading from Shell Piplelines

val input : (Stdlib.in_channel -> string) -> pipeline -> process_status * string

(input f pipeline) executes the shell pipeline (or simple command), applies f to a channel connected to the standard output, and returns the exit status and the result of f's evaluation.

Example:

  • input Prelude.readline @@ cmd ["uname";"-s"]

returns (Prelude.Unix.WEXITED 0, "Linux") on my system.

val read : ?ign:bool -> pipeline -> string

(read ?ign pipeline) executes the shell pipeline and returns just its standard output; any non-zero exit status raises Failure unless you pass ~ign:true, in which case the empty string is returned.

val readline : ?ign:bool -> pipeline -> string

(readline ?(ign=false) pipeline) executes the shell pipeline and returns just the first line of its standard output (sans end-of-line characters); any non-zero exit status raises Failure unless you pass ~ign:true, in which case the empty string is returned.

val readlines : ?ign:bool -> pipeline -> string list

(readlines ?(ign=false) pipeline) executes the shell pipeline and returns just the list of the lines of its standard output; any non-zero exit status raises Failure unless you pass ~ign:true, in which case the empty list is returned.

Output: Writing to Shell Piplelines

val output : (Stdlib.out_channel -> unit) -> pipeline -> process_status

(output f pipeline) executes the shell pipeline (or simple command), applies f to a channel connected to the pipeline's standard input, and returns the exit status.

Example: - output (fun c -> foreach (fprintf c "%d\n") (1,10)) (cmd ["dd";"of=/tmp/foo"])

returns Prelude.Unix.WEXITED 0, having written 10 lines to the file "/tmp/foo".

val write : ?ign:bool -> pipeline -> string -> unit

(write ?ign pipeline str) executes the shell pipeline, writing str to its standard input.

Any non-zero exit status raises Failure unless you pass ~ign:true, in which case the exit status is ignored.

val writelines : ?ign:bool -> pipeline -> string list -> unit

(writelines ?ign pipeline lines) executes the shell pipeline writing each element of lines to its status input, appending a newline to each.

Bidrectional I/O: Writing to and Reading from Shell Piplelines

val inout : ?env:string array -> pipeline -> (Stdlib.out_channel -> unit) -> (Stdlib.in_channel -> Stdlib.in_channel -> 'a) -> 'a

(inout ?env pipeline writer reader) calls writer to write data to the standard input of the pipeline, and then calls reader so se to read so (its standard output) and se (its standard error), returning the result.

env is the environment for the pipeline.

val sh : ?env:string array -> pipeline -> string -> string

(sh ?env pipeline str) writes str to the standard input of the pipeline, and then reads its standard output (ignoring stderr), returning the result.

env is the environment for the pipeline.