On 4/14/25 1:48 PM, Remi Forax wrote:
From: "Ron Pressler" <ron.press...@oracle.com>
This does what you want (and could even be combined to a single expression):

    Process p = new ProcessBuilder("ls", "-al").start();
    String result = p.inputReader().lines().collect(Collectors.joining("\n"));

and it’s even nicer in the cases where you may want to process the output line
by line, as many scripts do.

Hi Ron,
i think you need to close the inputReader

A few points here...

It might be possible to get away without any Process-related cleanup. For one, there's no "close" method on Process or ProcessBuilder. The destroy() method will certainly clean up, but you don't want that; and waitFor() merely waits for termination but doesn't actually clean anything up.

At least in the Unix ProcessImpl class, there's a bunch of infrastructure to handle exit of the underlying process, drain input from its stdout/stderr, and close the pipes. (I didn't look on Windows.) So setting aside termination, IOException, and what to do with stderr, it seems possible to just get the inputReader() and do something with the characters it emits.

Getting a stream of lines with lines() seems like a reasonable thing to do if you want to process the output line by line.

There are other possibilities, taking a nod from Files, which has methods readAllLines() and readString(). Putting similar methods on some class in the Reader family might help considerably here. Or you could call Reader.transferTo(Writer) that will send the characters to any Writer that might have a useful destination.

s'marks






   public static String output(String... args) {
     ProcessBuilder processBuilder = new ProcessBuilder(args);
     try {
       Process process = processBuilder.start();
       try (BufferedReader reader = process.inputReader()) {
         return reader.lines().collect(Collectors.joining("\n"));
       }
     } catch (IOException e) {
       throw new IOError(e);
     }
   }



— Ron


regards,
Rémi



On 14 Apr 2025, at 20:06, Cay Horstmann <cay.horstm...@gmail.com> wrote:

Absolutely, ProcessBuilder/Process is the right approach.

I realize that all those bells and whistles in the Process API are there for a
reason, but the API is a bit clunky for the happy day path that one usually has
in a script: running a process until it terminates and getting its output. It
is trivial to write a couple of helper methods, but it might be nice if the
Process API could help out. Something like

Process p = Process.waitFor("ls", "-al");
String result = p.output();

Cheers,

Cay

PS. This isn't pretty in Python either:
https://docs.python.org/3/library/subprocess.html#subprocess.run


Il 12/04/25 17:02, Ron Pressler ha scritto:
Hi.
Let’s focus on ProcessBuilder and Process (as I think that’s where you want to
focus, and why I think this discussion is more appropriate for core-libs-dev).
Can you try to show more concretely what the pain point is in your actual code?
The ProcessBuilder example is long because it does multiple things, each of
which may or may not be relevant to your use case. That doing five different
things requires five lines of code doesn’t help us see where your specific pain
point is.
— Ron
On 12 Apr 2025, at 15:39, David Alayachew <davidalayac...@gmail.com> wrote:

Hello Amber Dev Team and Kulla Dev Team,

(I made a reddit post too, if you prefer to interact there instead --
https://www.reddit.com/r/java/comments/1jx87ys/)
The following JEP's have released recently.
     • JEP 495: Simple Source Files and Instance Main Methods
     • JEP 330: Launch Single-File Source-Code Programs
     • JEP 222: jshell: The Java Shell (Read-Eval-Print Loop)
These have made it really easy for me to do CLI scripting in Java, as opposed to
Bash. However, I've run into some pain points, as I've relied more and more on
Java.
For starters, the hand off from Java --> Bash is kind of ugly. Bash --> Java is
not bad, due to void main(final String[] args), as well as Bash's xargs. But
Java --> Bash is ugly, and here is an example demonstrating how/why.
I use AWS CLI to manage my dev environment. It's super powerful, and is all
available directly from the CLI, using simple Bash or even CMD.
Let's say I use AWS CLI to gather some ad-hoc information about my entire dev
environment. How do I manage the multiple handoffs back and forth between AWS
CLI and Java?
There are no good answers.
     • Store the results into a file, then use JShell/java(c) to process the 
output
     file from Bash/AWS CLI.
         • There's multiple handoffs back and forth between AWS CLI and Java. 
So, every
         handoff from Java ---> AWS CLI means generating a new file, thus 
increasing the
         complexity and cruft. It's unideal.
     • Use Java's ProcessBuilder and Process classes.
         • This works, but is heavy-handed. Look at the examples in those 
links. That is
         multiple lines of code to represent a single bash command. It does 
appear to be
         the idiomatic way, though.
     • Do all upstream processing with AWS CLI in Bash directly, then do only a
     single handoff to Java, once I have done all I need to with AWS CLI.
         • This is definitely the least painful, but it also means I don't use 
much Java
         at all. And any changes in upstream processing must be done in Bash to 
avoid
         handoff headaches from AWS CLI ---> Java.
     • Download the AWS SDK Jar files and just do it all in Java.
         • Ignoring the fact that some things are much harder to do via the AWS 
Java
         SDK's, there's actually some functionality that just isn't available 
via the
         Java ones. I'd have to recreate it myself, and it would be a 
significant lift.
Option 4 is best when I am building an application, but for ad-hoc checks that I
want to do on the fly (my most common use-case by far), I have been using
Option 3.
I just wish I could use more Java. It's a FAR BETTERtool than Bash, but I can't
justify the level of effort for ad-hoc use cases because of the poor hand off
from Java --> Bash. And since AWS CLI is only available via Bash/CMD, I'm stuck
with a bunch of not-good choices.
CLI Scripting in Java is great, but I wanted to highlight this pain point to
spread awareness.
Can you relate?


--

Cay S. Horstmann | https://horstmann.com

Reply via email to