How to pipe input to a process using Exec?

I need to be able to pipe an input file to a process I’m exec’ing. The exact use case is executing a SQL file in MySQL like so:

mysql -u username -ppassword mydb < create_log_table.sql

I use project.exec() within another task:

exec {
    commandLine "cmd", "/c", "mysql", "-u", "username", "-ppassword", "mydb", "<", "create_log_table.sql"
}

That produces an error: “Process ‘command ‘cmd’’ finished with non-zero exit value 1”. I attempted a couple of variations, “< create_log_table.sql” and “mydb < create_log_table.sql” as arguments but none of those work.

Is there a recommended way to pipe an input file to an exec’ed process that I’m missing?

Ryan

So I did a little digging, and under the hood Gradle uses java.lang.ProcessBuilder to create the process.

Based on a similar StackOverflow question, one way to handle this is to encapsulate the entire argument line in a single argument.

So my example above becomes:

exec {
    commandLine "cmd", "/c mysql -u username -ppassword mydb < create_log_table.sql"
}

This works. I guess then I wonder what the advantage of separating out the arguments is, in that case.

How command line arguments need to be separated depends on the expectations of the executable (‘cmd’ in this case).

Ok, good to know, thanks.

Ok, good to know, thanks.

Ok, good to know, thanks.

Do you need to use cmd here?

Would this work?

exec {
    commandLine "mysql", "-u", "username", "-ppassword", "mydb"
    doFirst {
      inputStream = new FileInputStream(file("create_log_table.sql"))
    }
}

Sorry, I don’t know how I missed your reply, Luke. Yes, that would work much better. I was thinking I needed to invoke a separate interpreter, but upon reflection I realized I don’t have to.