My experience using Java to do CLI Scripting

Ron Pressler ron.pressler at oracle.com
Mon Apr 14 20:30:40 UTC 2025


(moved from amber-dev)

Hi.

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.

Now, does that code deserve its own method in the JDK? Isn’t it about as common to want to process line by line as they’re output by the process? Isn’t it also quite common to care about the standard error? Isn’t such a method short enough to be declared in a script?

But let’s see what we’re left with if we just remove the accidental complexity in the code above, which, I think, is mostly in `.lines` and `Collectors.joining("\n”)`. Imagine (and this is not a proposal, just a thought) we had  `Process.inputLines()` that returns `inputReader().lines()` and a `Collectors.joiningLines()`, and the code would look like this:

    Process p = new ProcessBuilder("ls", "-al").start();
    String result = p.inputLines().collect(Collectors.joiningLines());

I think that be almost as succinct as your API without giving up any flexibility. The only accidental complexity remaining here, I think, is the call to `start` (which can’t be removed if you're interested in the standard error).

Some ideas floated in the “on ramp” area (although in this case we’re talking about script-writers rather than Java beginners) focus on combining acquiring data and aggregating/parsing it, and I just don’t know how useful that is, given how easily things can be composed.

— Ron



> On 14 Apr 2025, at 20:06, Cay Horstmann <cay.horstmann at 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 <davidalayachew at 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
> 



More information about the core-libs-dev mailing list