Issue
I'm encountering an issue executing a command using Kotlin's ProcessBuilder. The command is being split into multiple arguments, resulting in an error: at most 1 query string can be specified as an argument, got 10
.
Relevant Code:
override fun fetchRecords(startTime: String, stopTime: String, bucket: String): List<String> {
val result = runCommand(
"influx query 'from(bucket: \"$bucket\") |> range(start: $startTime) |> pivot(rowKey: [\"_time\"], columnKey:[\"_field\"], valueColumn:\"_value\")'"
)
// ...
}
private fun runCommand(command: String, workingDir: File = File(".")): String {
val parts = command.split("\\s".toRegex())
val proc = ProcessBuilder(*parts.toTypedArray())
// ...
}
Error Message:
Command error: Error: at most 1 query string can be specified as an argument, got 10
Attempted Fixes:
- I've tried using a multi-line string literal without explicit newline characters, but the error persists.
Questions:
- What's causing the incorrect argument splitting?
- How can I ensure the command is passed as a single argument? -Are there alternative approaches to executing commands in Kotlin that might avoid this issue?
- Should I consider using a different library for command execution?
Additional Context:
- I'm using Kotlin version
1.9.20
- The command being executed is
influx query 'from(bucket: "1CATUSDTTimeSeries1Hour") |> range(start: 0) |> pivot(rowKey: ["_time"], columnKey:["_field"], valueColumn:"_value")'
which works fine with terminal.
Any guidance would be greatly appreciated!
Solution
Instead of parsing the command line arguments yourself (which is not trivial), take an Array<String>
instead, and let the caller split the arguments.
private fun runCommand(command: Array<String>, workingDir: File = File(".")): String {
val proc = ProcessBuilder(*command)
...
}
val result = runCommand(
arrayOf("influx", "query",
"from(bucket: \"$bucket\") |> range(start: $startTime) |> pivot(rowKey: [\"_time\"], columnKey:[\"_field\"], valueColumn:\"_value\")"
)
)
Alternatively, send the whole command to sh
(or whatever shell is on the system), and let it parse the arguments. This of course, is platform dependent.
private fun runCommand(command: String, workingDir: File = File(".")): String {
val proc = ProcessBuilder(arrayOf("sh", "-c", command))
...
}
Answered By - Sweeper Answer Checked By - Clifford M. (WPSolving Volunteer)