Search code examples
javaprocessruntime.execprocessbuilder

runtime.exec with spaces in the parameters


I want to execute bash commands (on a Linux system) from Java. The command I want to execute is:

    /usr/bin/convert -pointsize 24 label:'Just a test.' ./dummy.png

I first used:

    runtime.exec("/usr/bin/convert -pointsize 24 label:'Just a test.' ./dummy.png");

This worked, but used "Just" as a label instead of: "Just a test.". I now use:

    runtime.exec(new String []{"/usr/bin/convert", "-pointsize 24", "label:'Just a test.'", "./dummy.png"});

This does not give an error, but there is no dummy.png generated.

How could I get this to work?

-- Edit:

With the help of MadProgrammer I solved the problem. I thought it a good idea to show a working example:

    import java.util.Scanner;
    import java.io.*;

    public class SystemCommand {
        // public #########################
        public static void main(String[] args) {
            try {
                doCommand(new String[] {"/usr/bin/convert",
                                        "-background", BACKGROUND,
                                        "-fill",       FILL,
                                        "-font",       FONT,
                                        "-pointsize",  FONTSIZE,
                                        "label:" +     CITATION,
                                        FILENAME});
            }
            catch (IOException e) {
                System.out.println(e.getMessage());
            }
        }


        // private ########################
        final static String INDENT     = "    ";

        final static String AUTHOR     = "Bruce Lee";
        final static String BACKGROUND = "NavyBlue";
        final static String CITATION   =
            "\n"   +
            INDENT + "We all have time to either spend or waste"  + INDENT + "\n" +
            INDENT + "and it is our decision what to do with it." + INDENT + "\n" +
            INDENT + "But once passed, it is gone forever."       + INDENT + "\n" +
            "\n"   +
            INDENT + AUTHOR                                       + INDENT + "\n";
        final static String FILENAME   = "citation.png";
        final static String FILL       = "Yellow";
        final static String FONT       = "Bookman-DemiItalic";
        final static String FONTSIZE   = "24";

        static Runtime runtime = Runtime.getRuntime();


        private static void doCommand(final String[] cmd) throws IOException {
            int     i;
            Process p;
            Scanner sc;

            p  = runtime.exec(cmd);
            sc = new Scanner(p.getInputStream());
            while (sc.hasNext()) {
                System.out.println(sc.nextLine());
            }
        }
    }

To test it in Linux (Image Magick has to be installed):

    javac SystemCommand.java && java SystemCommand && display citation.png

When I made an example with ProcessBuilder I will add it here also.

-- Edit

The ProcessBuilder variant. In this case it is not very useful, but when you do something more complex, it will be a better solution.

/*
  I needed to write some code that executes something in the Bash shell.
  This is not to difficult, but when there are spaces, things can become difficult.
  But if you know how it works, then there is no problem.

  It can be done Runtime.getRuntime().exec. In this example that would be good enough.
  (See SystemCommand.java) But when you have a little bit more difficult things to do,
  it is better to use ProcessBuilder. That I do in this example.

  The solution is: create a String array in which the first entry is the command
  and every parameter has his own entry (without quoutes).

  This program is the equavelent of:
      /usr/bin/convert -background "NavyBlue" -fill "Yellow" -font "Bookman-DemiItalic" -pointsize 24 label:"
          I hope I shall always possess
          firmness and virtue enough
          to maintain
          what I consider the most
          enviable of all titles,
          the character of an honest man.

          George Washington" citation.png

  To  test it:
      javac  SystemCommandWithProcessBuilder.java && \
        java SystemCommandWithProcessBuilder      && \
        display citation.png

  To use this you need of-course Java, but besides that ImageMagick needs to be installed.
  It is written for Linux.
 */

import java.io.*;

public class SystemCommandWithProcessBuilder {
    // public #########################
    public static void main(String[] args) {
        try {
            doCommand(new String[] {"/usr/bin/convert",
                                    "-background", BACKGROUND,
                                    "-fill",       FILL,
                                    "-font",       FONT,
                                    "-pointsize",  FONTSIZE,
                                    "label:" +     CITATION,
                                    FILENAME});
        }
        catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }


    // private ########################
    final static String INDENT     = "    ";

    final static String AUTHOR     = "George Washington";
    final static String BACKGROUND = "NavyBlue";
    final static String CITATION   =
        "\n"   +

        INDENT + "I hope I shall always possess"   + INDENT + "\n" +
        INDENT + "firmness and virtue enough"      + INDENT + "\n" +
        INDENT + "to maintain"                     + INDENT + "\n" +
        INDENT + "what I consider the most"        + INDENT + "\n" +
        INDENT + "enviable of all titles,"         + INDENT + "\n" +
        INDENT + "the character of an honest man." + INDENT + "\n" +
        "\n"   +
        INDENT + AUTHOR                            + INDENT + "\n";
    final static String FILENAME   = "citation.png";
    final static String FILL       = "Yellow";
    final static String FONT       = "Bookman-DemiItalic";
    final static String FONTSIZE   = "24";


    private static void doCommand(final String[] cmd) throws IOException {
        BufferedReader      br;
        String              line;
        Process             p;

        p   = new ProcessBuilder(cmd).start();
        br  = new BufferedReader(new InputStreamReader(p.getInputStream()));
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
    }
}

To test it in Linux (Image Magick has to be installed):

javac  SystemCommandWithProcessBuilder.java && \
  java SystemCommandWithProcessBuilder      && \
  display citation.png

I have published both at: https://github.com/CecilWesterhof/JavaExamples


Solution

  • First of all, use ProcessBuilder it simplerfies the over all process

    Having said that, each element in the String array is considered an individual parameter to the command, that is, this is exactly how the commands args[] array will look.

    You could try something like...

    runtime.exec(new String []{"/usr/bin/convert", "-pointsize", "24", "label:'Just a test.'", "./dummy.png"})