Search code examples
javalinuxprocessbuilder

How to use ProcessBuilder when using redirection in Linux


I want to run this command using ProcessBuilder:

sort -m -u -T /dir -o output <(zcat big-zipped-file1.gz | sort -u) <(zcat big-zipped-file2.gz | sort -u) <(zcat big-zipped-file3.gz | sort -u) 

I have tried the following:

// This doesn't recognise the redirection.
String[] args = new String[] {"sort", "-m", "-u", "-T", "/dir", "-o", "output", "<(zcat big-zipped-file1.gz | sort -u)", "<(zcat big-zipped-file2.gz | sort -u)", "<(zcat big-zipped-file3.gz | sort -u)"};

// This gives:
// /bin/sh: -c: line 0: syntax error near unexpected token `('
String[] args = new String[] {"/bin/sh", "-c", "\"sort -m -u -T /dir -o output <(zcat big-zipped-file1.gz | sort -u) <(zcat big-zipped-file2.gz | sort -u) <(zcat big-zipped-file3.gz | sort -u)\""};

I am using args like this: processBuilder.command(args);


Solution

  • I finally figured it out. As Roman has mentioned in his comment, sh does not understand redirection so I had to use bash. I also had to consume both the input stream and the error stream.

    String[] args = new String[] {"/bin/bash", "-c", "sort -m -u -T /dir -o output <(zcat big-zipped-file1.gz | sort -u) <(zcat big-zipped-file2.gz | sort -u) <(zcat big-zipped-file3.gz | sort -u)"};
    
    ProcessBuilder builder = new ProcessBuilder();
    builder.command(args);
    Process process = builder.start();
    BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
    BufferedReader error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
    while((line = input.readLine()) != null);
    while((line = error.readLine()) != null);
    
    process.waitFor();