Search code examples
javacmdprocessbuilder

"Program Files" command intern not found CMD


I use java to excute a command line to create a database, i get an error when i excute this piece of code:

private final String POSTGRES_PATH = "\"C:\\Program Files\\PostgreSQL\\9.3\\bin\\psql.exe\"";
private final String DATA_BASE = "bd_name";

private void creerDataBase() {
    String command = this.POSTGRES_PATH + " -U postgres -d postgres -c \"CREATE DATABASE " + this.DATA_BASE + "\"";
    System.out.println("command = " + command);
    String creerBDD = executerCommande(command);
    System.out.println("Resultat : " + creerBDD);
}

public String executerCommande(String command) {
    String line;
    String resultat = "";
    try {
        ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", command);
        builder.redirectErrorStream(true);
        Process p = builder.start();
        BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
        while (true) {
            line = r.readLine();
            if (line == null) {
                break;
            }
            resultat += line + "\n";
        }
    } catch (Exception e) {
        System.out.println("Exception = " + e.getMessage());
    }
    return resultat;
}

I get this result:

command = "C:\Program Files PostgreSQL\9.3\bin\psql.exe"\ -U postgres -d postgres -c "CREATE DATABASE bd_name"

and this error:

'C:\Program' n'est pas reconnu en tant que commande interne

This mean that Program is not an intern command.

but when i excute this command in CMD it work fine?

Is there any way to Build this Path because the ProcessBuilder not recognize C:\Program Files


Solution

  • Don't run cmd.exe if you want to run a separate binary program.
    cmd.exe is for scripts like *.cmd or *.bat

    With cmd.exe you have to pass your command as an argument of CMD, and you should manage all OS-specific pitfalls like long paths with whitespaces, quotes inside qoutes etc.

    Instead, you had better run psql itself.
    The ProcessBuilder takes a command and all the arguments as a list of separate strings. And ProcessBuilder is clever enough to do all the necessary magic with quotes and whitespaces by itself.

    And take attention to the list of arguments - shells separate arguments by whitespaces, while psql might recognize the sequence of strings as a single argument.
    We may assume that -U postgress is a single argument for psql, but for shell (cmd.exe in our case) these are two separate arguments - -U and postgress, so we should pass them to the ProcessBuilder separately

    So the better way to run psql is to run it directly, something like that:

     new ProcessBuilder("C:\\Program Files\\PostgreSQL\\9.3\\bin\\psql.exe", 
                        "-U", "postgres", 
                        "-d", "postgres", 
                        "-c", "\"CREATE DATABASE " + this.DATA_BASE + "\"");