How to use environment variables in CMD using Java?

Tags: ,

I am new to using the ProcessBuilder object to run commands inside of Java. My issue is that when I put my environment variables into the builder.command(...) method, it doesn’t work. However, when I hardcode the strings of the environment variables, it works perfectly. Here is my code below along with an explanation to help make clear on what I am doing:

ProcessBuilder builder = new ProcessBuilder();;
    System.out.println("The user's chosen directory is: ";
    Map<String, String> environment = builder.environment();
    environment.forEach((key,value)->System.out.println("key is "+key+" "+"value: "+value));
    builder.command("ffmpeg", "-i", "$WINDOW","-i", "$AUDIO", "-vcodec", "copy" ,"output.mp4");

    Process pr= builder.start();


Basically I have a JButton in which an ActionListener is being fired off when the user clicks it. I am trying to use ffmpeg to convert an audio and video file together into one file if they desire. This code above will be executed in which I am trying to get the directory of the file they chose in my application to store the two files mentioned previously. Through using, I am able to change the current directory of builder to that of the user’s. I then created a map called environment in which I could add two environment variables called WINDOW and AUDIO. The two env. variables were assigned file names such that the file names were assigned to two variables w and a which are of type string. I did check to see if they were in the map and they were. I then attempt to make my set of instructions using the builder.command(...) method and then start the process using builder.start().


However, the singleoutput.mp4 file was not created and when I checked my Process using the waitFor() method I get a “1”. On the contrary, when I don’t use env. variables at all and hardcode the file names in between the parantheses where the env. variables were, it works correctly. So, exactly what am I doing wrong in my builder.command(..)? Thanks.


It strikes me that the simplest solution is:

builder.command("ffmpeg", "-i", w ,"-i", a, "-vcodec", "copy" ,"output.mp4");

There is no need to set environment variables if you are only going to use them to inject command line arguments.

However, if you do want to do it via environment variables, then the simple way is to use a subshell to do all of the command line parsing and expansion; e.g.

builder.command("/bin/sh", "-c", 
                "ffmpeg -i $WINDOW -i $AUDIO -vcodec copy output.mp4");

You could also use quoting, globbing, pipelines, redirection and all of the other fancy shell features.

Source: stackoverflow