Suppose something like this:
execInCurrentShell("cd /")
System.out.println("Ran command : cd /")
is in the main()
function of MyClass
So that when I run the class, I cd
into the /
directory
user@comp [~] pwd
/Users/user
user@comp [~] java MyClass
Ran command : cd /
user@comp [/] pwd
/
The usual way to run shell commands, that is, through the Runtime
class:
Runtime.getRuntime().exec("cd /")
Won't work here because it doesn't run the command in the current shell but in a new shell.
What would the execInCurrentShell()
function (the one that actually works) look like?
You won't be able to run commands that affect the current invoking shell, only to run command line bash/cmd as sub-process from Java and send them commands as follows. I would not recommend this approach:
String[] cmd = new String[] { "/bin/bash" }; // "CMD.EXE"
ProcessBuilder pb = new ProcessBuilder(cmd);
Path out = Path.of(cmd[0]+"-stdout.log");
Path err = Path.of(cmd[0]+"-stderr.log");
pb.redirectOutput(out.toFile());
pb.redirectError(err.toFile());
Process p = pb.start();
String lineSep = System.lineSeparator();
try(PrintStream stdin = new PrintStream(p.getOutputStream(), true))
{
stdin.print("pwd");
stdin.print(lineSep);
stdin.print("cd ..");
stdin.print(lineSep);
stdin.print("pwd");
stdin.print(lineSep);
};
p.waitFor();
System.out.println("OUTPUT:"+Files.readString(out));
System.out.println("ERROR WAS: "+Files.readString(err));
}
This also works for CMD.EXE on Windows (with different commands). To capture the response per command you should replace use of pb.redirectOutput()
with code to read pb.getInputStream() if you really need the responses per line rather than as one file.