----- Original Message ----- > From: "Ron Pressler" <ron.press...@oracle.com> > To: "cay horstmann" <cay.horstm...@gmail.com> > Cc: "core-libs-dev" <core-libs-dev@openjdk.org>, "David Alayachew" > <davidalayac...@gmail.com> > Sent: Monday, April 14, 2025 10:30:40 PM > Subject: Re: My experience using Java to do CLI Scripting
> (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. Hi Ron, i think you need to close the inputReader 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