How to pipe a string argument to an executable launched with Apache Commons Exec?

前端 未结 2 1365
梦毁少年i
梦毁少年i 2020-12-16 18:43

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

相关标签:
2条回答
  • 2020-12-16 19:00

    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;
    }
    
    0 讨论(0)
  • 2020-12-16 19:07

    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).

    0 讨论(0)
提交回复
热议问题