0

I have a command in array format that I can pass to execve(). For example, the command is:

echo "It's Nice"

and the array I have is ["echo","It's Nice"]. I'm trying to convert this array into a string that I can write in bash and execute properly. I obviously cannot join on this array with space delimiter because I will get: echo It's Nice which cannot be run since it has an unterminated single quote.

Is there a BKM to convert this to a runnable string? maybe a library that does that already in Java? It can get tricky when the command has many special characters that should be escaped\quoted in order to run properly.

EDIT: I would like to make my question clearer. The user gives me his command as a string array, I execute it and everything works fine. Now I need to report to the user what I have ran. I do not want to show the command as an array, instead I would like to show it as a string that the user can simply copy and paste to his bash shell and execute it if he wants to. So my input is [echo, It's Nice] and my output should be echo "It's Nice". It seems like a simple function to write, but i'm not sure i'm thinking of all the end-cases here (like if the string has a quote or some other special character the shell manipulates). I was wondering maybe there's some code that already does that and covers the end cases i'm yet to think about.

ItamarBe
  • 482
  • 1
  • 5
  • 12

2 Answers2

0

You don't need to convert array to string, you can directly execute a command using ProcessBuilder:

String runShell(final String[] commandArgs) {   
    try {
        final ProcessBuilder processBuilder = new ProcessBuilder(commandArgs);
        processBuilder.redirectErrorStream(true); // merge stderr with stdout
        Process process = processBuilder.start();
        ret = process.waitFor();
        BufferedReader br = new BufferedReader(new InputStreamReader(
                                                  process.getInputStream() ));
        br.lines().forEach(System.out::println); // print stdout + stderr
        process.destroy();
        br.close();
    } 
    catch (IOException|InterruptedException e) { 
        e.printStackTrace(); 
    }
    return commandArgs[0] + Arrays.asList(commandArgs).stream()
    .skip(1)
    .collect(Collectors.joining("\" \"", " \"", "\""));
}

and call it as:

runShell(new String[] {"pwd"}); // print current working directory
runShell(new String[] {"ls", "-l"}); // list all the files and directories
runShell(new String[] {"echo", "It's Nice"}); // echo something
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • Actually i'm asking for reporting, i have no problem running the command but i want to tell the user what i ran and that he will be able to copy paste it to the shell if he needs to run it again – ItamarBe Nov 29 '15 at 16:13
  • `processBuilder.command()` will give you the command that is being run – anubhava Nov 29 '15 at 16:15
  • Will it give it even if i dont execute? Im running the command in a different way – ItamarBe Nov 29 '15 at 16:17
  • It is difficult to answer without seeing your code. If you show your code then I can suggest something. – anubhava Nov 29 '15 at 16:25
  • `processBuilder.command()` returns a list, in the third case above it will return `[echo , It's Nice]` when i actually need the string `echo "It's Nice"`. I will modify the question to make it clearer – ItamarBe Nov 30 '15 at 16:10
  • It won't work, if some element in the array has a space it should be quoted, but if the string already contains quotes they should be escaped. the answer to this is not trivial, that's why i'm asking it here. i can write code that does what i described but there maybe more end-cases i haven't thought of. – ItamarBe Nov 30 '15 at 16:40
0

That's easy to do in Java 8:

String joined = String.join(" ", iteratable);
Abdulhafeth Sartawi
  • 1,086
  • 1
  • 11
  • 20