Skip to content

clojure.java.shell/sh

View this page on ClojureDocs

Type: function Added: Clojure 1.2 Examples: 12 Runnable: 1
([& args])

Passes the given strings to Runtime.exec() to launch a sub-process.

Options are

:in may be given followed by any legal input source for clojure.java.io/copy, e.g. InputStream, Reader, File, byte[], or String, to be fed to the sub-process's stdin. :in-enc option may be given followed by a String, used as a character encoding name (for example "UTF-8" or "ISO-8859-1") to convert the input string specified by the :in option to the sub-process's stdin. Defaults to UTF-8. If the :in option provides a byte array, then the bytes are passed unencoded, and this option is ignored. :out-enc option may be given followed by :bytes or a String. If a String is given, it will be used as a character encoding name (for example "UTF-8" or "ISO-8859-1") to convert the sub-process's stdout to a String which is returned. If :bytes is given, the sub-process's stdout will be stored in a byte array and returned. Defaults to UTF-8. :env override the process env with a map (or the underlying Java String[] if you are a masochist). :dir override the process dir with a String or java.io.File.

You can bind :env or :dir for multiple operations using with-sh-env and with-sh-dir.

sh returns a map of :exit => sub-process's exit code :out => sub-process's stdout (as byte[] or String) :err => sub-process's stderr (String via platform default encoding)

Examples

by zk on . May have evaluation errors.
by secondplanet on . May have evaluation errors.
by franks42 on . May have evaluation errors.
by jafingerhut on
by octopusgrabbus on . May have evaluation errors.
by octopusgrabbus on . May have evaluation errors.
by Atsman on . May have evaluation errors.
by claj on . May have evaluation errors.
by claj on . May have evaluation errors.
by Saikyun on . May have evaluation errors.
by Crowbrammer on . May have evaluation errors.
by avocade on . May have evaluation errors.

Note by ejschoen

It's worth noting that sh begins interpreting arguments starting with the first non-string (not just keywords!) as key-value pairs, as in the example above with pwd. This means that even if an argument's type has a trivial conversion to a string, such as an integer or boolean, it must be stringified. If not, it'll be passed as an argument to hash-map, and you might see an IllegalArgumentException if there are an odd number of arguments beginning with the first non-string.

Note by geokon-gh

As noted in the 4th example, sh uses futures. This means that if your program uses sh and then finishes its execution it will unexpectedly hang and not terminate/exit. The sh future will still be alive in the background and will be holding up the program.

This is a bit confusing when you first try to use Clojure for scripting as it looks like your script doesn't exit naturally. Furthermore, when you run sh in the REPL the background futures aren't apparent to the user and everything works as-expected

To fix the situation you can either run (System/exit 0) to terminate your program explicitly. Or you can run (shutdown-agents) to kill the background future and then the program will exit naturally

For a discussion of this strange behavior see: https://clojureverse.org/t/why-doesnt-my-program-exit/3754/2

See also


Content from the matching ClojureDocs page, with authors credited on each contribution.