I want to invoke an external command from Kotlin code. In C/Perl, I would use system()
function. In Python, I would use the subprocess module. In Go, I would us
As this is the first google result when searching for how to run commands in kotlin, I found my self struggeling to extend it to get basic standard input working, as the Pipe "|" is not supported for the ProcessBuilder. I've found out how to do it, and thought I'd share. I've converted jkschneider's answer to be run as a simple function, now with optional stdin and output capturing. It's a little less pretty, but more flexible. You can run it like this:
exec("someCommandWithUserInput", stdIn = "yes")
/** Run a system-level command.
* Note: This is a system independent java exec (e.g. | doesn't work). For shell: prefix with "bash -c"
* Inputting the string in stdIn (if any), and returning stdout and stderr as a string. */
fun exec(cmd: String, stdIn: String = "", captureOutput:Boolean = false, workingDir: File = File(".")): String? {
try {
val process = ProcessBuilder(*cmd.split("\\s".toRegex()).toTypedArray())
.directory(workingDir)
.redirectOutput(if (captureOutput) ProcessBuilder.Redirect.PIPE else ProcessBuilder.Redirect.INHERIT)
.redirectError(if (captureOutput) ProcessBuilder.Redirect.PIPE else ProcessBuilder.Redirect.INHERIT)
.start().apply {
if (stdIn != "") {
outputStream.bufferedWriter().apply {
write(stdIn)
flush()
close()
}
}
waitFor(60, TimeUnit.SECONDS)
}
if (captureOutput) {
return process.inputStream.bufferedReader().readText()
}
} catch (e: IOException) {
e.printStackTrace()
}
return null
}