How to invoke external command from within Kotlin code?

exec, kotlin

Solution

Example of running a git diff by shelling out:

`"git diff".runCommand(gitRepoDir)`

Here are two implementations of the `runCommand` extension function:

1. Redirect to stdout/stderr

This wires any output from the subprocess to regular stdout and stderr:

fun String.runCommand(workingDir: File) {
    ProcessBuilder(*split(" ").toTypedArray())
                .directory(workingDir)
                .redirectOutput(Redirect.INHERIT)
                .redirectError(Redirect.INHERIT)
                .start()
                .waitFor(60, TimeUnit.MINUTES)
}

2. Capturing output as a String

An alternative implementation redirecting to `Redirect.PIPE` instead allows you to capture output in a `String`:

fun String.runCommand(workingDir: File): String? {
    try {
        val parts = this.split("\\s".toRegex())
        val proc = ProcessBuilder(*parts.toTypedArray())
                .directory(workingDir)
                .redirectOutput(ProcessBuilder.Redirect.PIPE)
                .redirectError(ProcessBuilder.Redirect.PIPE)
                .start()

        proc.waitFor(60, TimeUnit.MINUTES)
        return proc.inputStream.bufferedReader().readText()
    } catch(e: IOException) {
        e.printStackTrace()
        return null
    }
}

Problem

I want to invoke an external command from Kotlin code. - In C/Perl, I would use the `system()` function. - In Python, I would use the subprocess module. - In Go, I would use os/exec, and etc. But how do I do this in Kotlin?

Original source

Related problems