==================
External Processes
==================

Usage
=====

`sbt` includes a process library to simplify working with external
processes. The library is available without import in build definitions
and at the interpreter started by the :doc:`consoleProject <Console-Project>` task.

To run an external command, follow it with an exclamation mark `!`:

::

    "find project -name *.jar" !

An implicit converts the `String` to `sbt.ProcessBuilder`, which
defines the `!` method. This method runs the constructed command,
waits until the command completes, and returns the exit code.
Alternatively, the `run` method defined on `ProcessBuilder` runs the
command and returns an instance of `sbt.Process`, which can be used to
`destroy` the process before it completes. With no arguments, the
`!` method sends output to standard output and standard error. You can
pass a `Logger` to the `!` method to send output to the `Logger`:

::

    "find project -name *.jar" ! log

Two alternative implicit conversions are from `scala.xml.Elem` or
`List[String]` to `sbt.ProcessBuilder`. These are useful for
constructing commands. An example of the first variant from the android
plugin:

::

      <x> {dxPath.absolutePath} --dex --output={classesDexPath.absolutePath} {classesMinJarPath.absolutePath}</x> !

If you need to set the working directory or modify the environment, call
`sbt.Process` explicitly, passing the command sequence (command and
argument list) or command string first and the working directory second.
Any environment variables can be passed as a vararg list of key/value
String pairs.

::

     Process("ls" :: "-l" :: Nil, Path.userHome, "key1" -> value1, "key2" -> value2) ! log

Operators are defined to combine commands. These operators start with
`#` in order to keep the precedence the same and to separate them from
the operators defined elsewhere in `sbt` for filters. In the following
operator definitions, `a` and `b` are subcommands.

-  `a #&& b` Execute `a`. If the exit code is nonzero, return that
   exit code and do not execute `b`. If the exit code is zero, execute
   `b` and return its exit code.
-  `a #|| b` Execute `a`. If the exit code is zero, return zero for
   the exit code and do not execute `b`. If the exit code is nonzero,
   execute `b` and return its exit code.
-  `a #| b` Execute `a` and `b`, piping the output of `a` to the
   input of `b`.

There are also operators defined for redirecting output to `File`\ s
and input from `File`\ s and `URL`\ s. In the following definitions,
`url` is an instance of `URL` and `file` is an instance of
`File`.

-  `a #< url` or `url #> a` Use `url` as the input to `a`. `a`
   may be a `File` or a command.
-  `a #< file` or `file #> a` Use `file` as the input to `a`.
   `a` may be a `File` or a command.
-  `a #> file` or `file #< a` Write the output of `a` to `file`.
   `a` may be a `File`, `URL`, or a command.
-  `a #>> file` or `file #<< a` Append the output of `a` to
   `file`. `a` may be a `File`, `URL`, or a command.

There are some additional methods to get the output from a forked
process into a `String` or the output lines as a `Stream[String]`.
Here are some examples, but see the `ProcessBuilder
API <../../api/sbt/ProcessBuilder.html>`_
for details.

::

    val listed: String = "ls" !!
    val lines2: Stream[String] = "ls" lines_!

Finally, there is a `cat` method to send the contents of `File`\ s
and `URL`\ s to standard output.

Examples
--------

Download a `URL` to a `File`:

::

    url("http://databinder.net/dispatch/About") #> file("About.html") !
    or
    file("About.html") #< url("http://databinder.net/dispatch/About") !

Copy a `File`:

::

    file("About.html") #> file("About_copy.html") !
    or
    file("About_copy.html") #< file("About.html") !

Append the contents of a `URL` to a `File` after filtering through
`grep`:

::

    url("http://databinder.net/dispatch/About") #> "grep JSON" #>> file("About_JSON") !
    or
    file("About_JSON") #<< ( "grep JSON" #< url("http://databinder.net/dispatch/About") )  !

Search for uses of `null` in the source directory:

::

    "find src -name *.scala -exec grep null {} ;"  #|  "xargs test -z"  #&&  "echo null-free"  #||  "echo null detected"  !

Use `cat`::

    val spde = url("http://technically.us/spde/About")
    val dispatch = url("http://databinder.net/dispatch/About")
    val build = file("project/build.properties")
    cat(spde, dispatch, build) #| "grep -i scala" !
