Skip to content

Executing programs

Blocking and on the console

1
"npm install foobar"()

Reading to strings and lists

1
2
3
4
5
// Equivalent of `listing=$( ps ax )`
val listing = "ps ax".exec<String>()

// More useful: get the output as lines, drop the header line.
val listing: List<String> = "ps ax".exec().drop(1)

Redirects

1
2
3
4
5
6
7
8
"ps ax >listing.txt"()
"ps ax 2>listing.txt"()

// Multi-redirects.
"ps ax >listing1.txt >listing2.txt"()

// Redirect to a function; equivalent of 'ps ax | grep bash'
"ps ax >arg:1"({ if ("bash" in it) echo(it) })

Catching subprocess failures

1
2
3
4
5
6
7
8
try {
    "could-fail"()
} catch (e: Shell.SubprocessFailed) {
    if (e.errorCode != 1)
        throw e

    echo("Child died with ${e.signalName}")  // only on UNIX
}

A shorter way:

1
2
val result: String? = runCatching { "could-fail".exec() }.getOrNull()
if (result != null) { etc }

Environment variables

1
2
3
4
5
6
echo(env["FOO"])
env["HOME"] = mktmp().toString()   

subshell {
    env["SCOPED"] = "123"   // Set var only for this sub-shell.
}

Run in the background

1
2
3
4
5
val task = thread { 
    "npm install foo"() 
}

task.join()  // Wait for it.

Python

Python virtualenvs can be created in the hshell disk cache. The first time a set of packages is requested progress events are emitted as the venv is initialized and packages installed. The PATH and VIRTUAL_ENV env vars are set in that shell. When requested again the cache will be hit. The arguments can be a single path to a requirements file.

1
2
virtualenv("pandas>=1.2.3", "mkdocs-material")
"mkdocs --help"()