Search code examples
groovyjenkinsfindprocessbuilder

"find: missing argument to `-exec'" running in a Java process builder


I am trying to run the find command inside Jenkins (https://jenkins-ci.org) script console, which allows running groovy scripts from a web interface.

My code is:

ProcessBuilder pb = new ProcessBuilder();
pb.directory(new File("/var/lib/jenkins/jobs/myJob");
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
command = 'find . -name build.xml -exec echo \"{}\" \\;'
println(command)
pb.command(command.split(" "));
pb.start().waitFor();

The web UI will display the result of println:

find . -name build.xml -exec echo "{}" \;

While the jenkins log (/var/log/jenkins/jenkins.log) logs the following error:

find: missing argument to `-exec'

However, if I run that same command outputted in the web UI (find . -name build.xml -exec echo "{}" \;) through a shell I get no such error.

In addition, if I replace the \; witih +, the command works!

So something is fishy with processBuilder and the \\; being passed as a command line argument


Solution

  • The problem for the error with \; is that you are mixing shell escaping/quoting with the plain passing of params of the exec functions.

    Drop the \ before the ; and it works. ; needs \ only in the shell, since it is used to separate commands there. Same goes for quoting {} - when passing params to the exec*-style functions, no shell-style quoting/escaping is needed, since no shell interprets it (unless of course you run sh -c):

    def command = 'find . -name build.xml -exec echo {} ;' // XXX
    new ProcessBuilder()
        .directory(new File("/tmp"))
        .inheritIO()
        .command(command.split(" ")) // everything is just a list of strings
        .start()
    

    And this is basically the same thing in groovy:

    ("/tmp" as File).eachFileRecurse{
        if (it.name=="build.xml") {
            println it
        }
    }