I need to pipe a text argument to the stdin of a command launched with Apache Commons Exec (for the curious, the command is gpg and the argument is the passphrase to the key
Hi to do this i will use a little helper class like this: https://github.com/Macilias/Utils/blob/master/ShellUtils.java
basically you can than simulate the pipe usage like shown here before without calling the bash beforehand:
public static String runCommand(String command, Optional<File> dir) throws IOException {
String[] commands = command.split("\\|");
ByteArrayOutputStream output = null;
for (String cmd : commands) {
output = runSubCommand(output != null ? new ByteArrayInputStream(output.toByteArray()) : null, cmd.trim(), dir);
}
return output != null ? output.toString() : null;
}
private static ByteArrayOutputStream runSubCommand(ByteArrayInputStream input, String command, Optional<File> dir) throws IOException {
final ByteArrayOutputStream output = new ByteArrayOutputStream();
CommandLine cmd = CommandLine.parse(command);
DefaultExecutor exec = new DefaultExecutor();
if (dir.isPresent()) {
exec.setWorkingDirectory(dir.get());
}
PumpStreamHandler streamHandler = new PumpStreamHandler(output, output, input);
exec.setStreamHandler(streamHandler);
exec.execute(cmd);
return output;
}
You cannot add a pipe argument (|) because the gpg command won't accept that. It's the shell (e.g. bash) that interprets the pipe and does special processing when you type that commandline into the shell.
You can use ByteArrayInputStream to manually send data to the standard input of a command (much like bash does when it sees the |).
Executor exec = new DefaultExecutor();
CommandLine cl = new CommandLine("sed");
cl.addArgument("s/hello/goodbye/");
String text = "hello";
ByteArrayInputStream input =
new ByteArrayInputStream(text.getBytes("ISO-8859-1"));
ByteArrayOutputStream output = new ByteArrayOutputStream();
exec.setStreamHandler(new PumpStreamHandler(output, null, input));
exec.execute(cl);
System.out.println("result: " + output.toString("ISO-8859-1"));
This should be the equivalent of typing echo "hello" | sed s/hello/goodbye/ into a (bash) shell (though UTF-8 may be a more appropriate encoding).