How to invoke external command from within Kotlin code?

后端 未结 7 1438
花落未央
花落未央 2020-11-29 22:08

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

7条回答
  •  囚心锁ツ
    2020-11-29 22:27

    I wanted a few changes from the solution of jkschneider, as it didn't catch the error codes I got from the executed commands. Also I did a few refactorings to get this:

    directory exec "git status"
    

    or

    directory.execute("git", "commit", "-m", "A message")
    

    I also opted to throw exceptions for error codes and shortened the wait, but that can easily be altered according to taste.

    /**
     * Shorthand for [File.execute]. Assumes that all spaces are argument separators,
     * so no argument may contain a space.
     * ```kotlin
     *  // Example
     *  directory exec "git status"
     *
     *  // This fails since `'A` and `message'` will be considered as two arguments
     *  directory exec "git commit -m 'A message'"
     * ```
     */
    infix fun File.exec(command: String): String {
        val arguments = command.split(' ').toTypedArray()
        return execute(*arguments)
    }
    
    /**
     * Executes command. Arguments may contain strings. More appropriate than [File.exec]
     * when using dynamic arguments.
     * ```kotlin
     *  // Example
     *  directory.execute("git", "commit", "-m", "A message")
     * ```
     */
    fun File.execute(vararg arguments: String): String {
        val process = ProcessBuilder(*arguments)
            .directory(this)
            .start()
            .also { it.waitFor(10, TimeUnit.SECONDS) }
    
        if (process.exitValue() != 0) {
            throw Exception(process.errorStream.bufferedReader().readText())
        }
        return process.inputStream.bufferedReader().readText()
    }
    

提交回复
热议问题