Entering a series of commands in git bash through java code - java

Am trying to get a series of commands on git bash one after the other. I can open the terminal through the code but after that wasn't successful with entering anything. For instance this is the code I tried
String [] args = new String[] {"C:\\Program Files\\Git\\git-bash.exe"};
String something="hi how are you doing";
try {
ProcessBuilder p = new ProcessBuilder();
var proc = p.command(args).start();
var w = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
w.write(something);
} catch (IOException ioException){
System.out.println(ioException);
}
Please let know how to be able to do enter a series of commands into git bash through the code.

The problem is that the command git-bash.exe opens the terminal window but the window's input is still the keyboard, so trying to write to the OutputStream that is returned by method getOutputStream(), in class Process does nothing. Refer to this question.
As an alternative, I suggest using using ProcessBuilder to execute a series of individual git commands. When you do that, your java code gets the command output.
Here is a simple example that displays the git version.
import java.io.IOException;
public class ProcBldT4 {
public static void main(String[] args) {
// C:\Program Files\Git\git-bash.exe
// C:\Program Files\Git\cmd\git.exe
ProcessBuilder pb = new ProcessBuilder("C:\\Program Files\\Git\\cmd\\git.exe", "--version");
pb.inheritIO();
try {
Process proc = pb.start();
int exitStatus = proc.waitFor();
System.out.println(exitStatus);
}
catch (IOException | InterruptedException x) {
x.printStackTrace();
}
}
}
When you run the above code, the git version details will be written to System.out.
Also, if the git command fails, the error details are written to System.err.
You need to repeat the code above for each, individual git command that you need to issue.

Related

How to have java run terminal commands on Mac? (Echo command)

How do you have java run commands on Mac? I see some examples of complex commands that is hard to follow. If I wanted to run a simple echo command from java, how would I do that? Not using osascript yet. Just want to see how you would send an echo from java to terminal.
public static void main(String[] args) throws IOException {
ProcessBuilder x = new ProcessBuilder("echo"," hi");
x.start();
}
This is the code I tried, but it does not work.
I think this question can help people who are trying to learn the basics of ProcessBuilder.
I am on Windows so the below code uses Windows echo. I hope you know the Mac echo command so that you can replace my command with yours.
import java.io.IOException;
import java.lang.ProcessBuilder;
public class PrcBldT2 {
public static void main(String[] args) {
// This command is for Windows operating system.
// For MacOS, try: new ProcessBuilder("echo", "hi")
ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", "echo", "hi");
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
try {
Process p = pb.start();
int result = p.waitFor();
System.out.println("Exit status = " + result);
}
catch (IOException | InterruptedException x) {
x.printStackTrace();
}
}
}
Note that each word in the command is a separate string. The echo command output will be redirected to System.out.

How can I use either Runtime.exec() or ProcessBuilder to open google chrome through its pathname?

I am writing a java code that has the purpose of opening a URL on youtube using Google Chrome but I have been unsuccessful in understanding either method. Here is my current attempt at it.
import java.lang.ProcessBuilder;
import java.util.ArrayList;
public class processTest
{
public static void main(String[] args)
{
ArrayList<String> commands = new ArrayList<>();
commands.add("cd C:/Program Files/Google/Chrome/Application");
commands.add("chrome.exe youtube.com");
ProcessBuilder executeCommands = new ProcessBuilder( "C:/WINDOWS/System32/WindowsPowerShell/v1.0/powershell.exe", "cd C:/Program Files/Google/Chrome/Application", "chrome.exe youtube.com");
}
}
It compiles OK, but nothing happens when I run it. What is the deal?
As stated by Jim Garrison, ProcessBuilder's constructor only executes a single command. And you do not need to navigate through the directories to reach the executable.
Two possible solutions for your problem (Valid for my Windows 7, be sure to replace your Chrome path if neccesary)
With ProcessBuilder using constructor with two parameters: command, argument (to be passed to command)
try {
ProcessBuilder pb =
new ProcessBuilder(
"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
"youtube.com");
pb.start();
System.out.println("Google Chrome launched!");
} catch (IOException e) {
e.printStackTrace();
}
With Runtime using method exec with one parameter, a String array. First element is the command, following elements are used as arguments for such command.
try {
Runtime.getRuntime().exec(
new String[]{"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
"youtube.com"});
System.out.println("Google Chrome launched!");
} catch (Exception e) {
e.printStackTrace();
}
you shoule invoke start method to execute the operation, like this:
ProcessBuilder executeCommands = new ProcessBuilder( "C:/WINDOWS/System32/WindowsPowerShell/v1.0/powershell.exe", "cd C:/Program Files/Google/Chrome/Application", "chrome.exe youtube.com");
executeCommands.start();

java variable linked to batch file

I am currently learning java and I encountered this problem. I am not sure if it can be done like this as I am still in the learning stage. So in my java main coding:
import java.io.File;
import java.io.IOException;
public class TestRun1
{
public static void main(String args[])
{
//Detect usb drive letter
drive d = new drive();
System.out.println(d.detectDrive());
//Check for .raw files in the drive (e.g. E:\)
MainEntry m = new MainEntry();
m.walkin(new File(d.detectDrive()));
try
{
Runtime rt = Runtime.getRuntime();
Process p = rt.exec("cmd /c start d.detectDrive()\\MyBatchFile.bat");
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
The "cmd /c start d.detectDrive()\MyBatchFile.bat" does not work. I do not know how to replace the variable.
And i created a batch file (MyBatchFile.bat):
#echo off
set Path1 = d.detectDrive()
Path1
pause
set Path2 = m.walkin(new File(d.detectDrive()))
vol231.exe -f Path2 imageinfo > Volatility.txt
pause
exit
It does not work. Please do not laugh.
I really isn't good in programming since I just started on java and batch file. Can anyone help me with it? I don't want to hard code it to become a E: or something like that. I want to make it flexible. But I have no idea how to do it. I sincerely ask for any help.
Procedure:
You should append the return value of the method which detects the drive, to the filename and compose the proper Batch command string.
Steps:
Get the return value of the method
String drive = d.detectDrive();
so, drive contains the value E:
append the value of drive to the filename
drive+"\MyBatchFile.bat"
so, we have E:\MyBatchFile.bat
append the result the batch command
cmd /c start "+drive+"\MyBatchFile.bat
result is cmd /c start E:\MyBatchFile.bat
So to invoke the batch command, the final code should be as follows:
try {
System.out.println(d.detectDrive());
Runtime rt = Runtime.getRuntime();
String drive = d.detectDrive();
// <<---append the return value to the compose Batch command string--->>
Process p = rt.exec("cmd /c start "+drive+"\\MyBatchFile.bat");
}
catch (IOException e) {
e.printStackTrace();
}

How can I run multiple commands in just one cmd windows in Java?

what I would like to do is run a batch file multiple times from a java application. Therefore I set up a for-loop that runs this code n times:
for (int i = 0; i < n; i++) {
Runtime.getRuntime().exec("cmd /c start somefile.bat");
}
The problem is that now each time the command is run a new cmd window pops up. However, what I want is just one window that pops up at the beginning and that is used to display all data from the following command calls.
How can I do that?
With && you can execute more than one commands, one after another:
Runtime.getRuntime().exec("cmd /c \"start somefile.bat && start other.bat && cd C:\\test && test.exe\"");
Using multiple commands and conditional processing symbols
You can run multiple commands from a single command line or script using conditional processing symbols. When you run multiple commands with conditional processing symbols, the commands to the right of the conditional processing symbol act based upon the results of the command to the left of the conditional processing symbol.
For example, you might want to run a command only if the previous command fails. Or, you might want to run a command only if the previous command is successful.
You can use the special characters listed in the following table to pass multiple commands.
& [...] command1 & command2
Use to separate multiple commands on one command line. Cmd.exe runs the first command, and then the second command.
&& [...] command1 && command2
Use to run the command following && only if the command preceding the symbol is successful. Cmd.exe runs the first command, and then runs the second command only if the first command completed successfully.
|| [...] command1 || command2
Use to run the command following || only if the command preceding || fails. Cmd.exe runs the first command, and then runs the second command only if the first command did not complete successfully (receives an error code greater than zero).
( ) [...] (command1 & command2)
Use to group or nest multiple commands.
; or , command1 parameter1;parameter2
Use to separate command parameters.
I would use Java's ProcessBuilder or another class which simulates/uses a shell. The following snippet demonstrates the idea (for Linux with bash).
import java.util.Scanner;
import java.io.*;
public class MyExec {
public static void main(String[] args)
{
//init shell
ProcessBuilder builder = new ProcessBuilder( "/bin/bash" );
Process p=null;
try {
p = builder.start();
}
catch (IOException e) {
System.out.println(e);
}
//get stdin of shell
BufferedWriter p_stdin =
new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
// execute the desired command (here: ls) n times
int n=10;
for (int i=0; i<n; i++) {
try {
//single execution
p_stdin.write("ls");
p_stdin.newLine();
p_stdin.flush();
}
catch (IOException e) {
System.out.println(e);
}
}
// finally close the shell by execution exit command
try {
p_stdin.write("exit");
p_stdin.newLine();
p_stdin.flush();
}
catch (IOException e) {
System.out.println(e);
}
// write stdout of shell (=output of all commands)
Scanner s = new Scanner( p.getInputStream() );
while (s.hasNext())
{
System.out.println( s.next() );
}
s.close();
}
}
Please note that it is only a snippet, which needs to be adapted for Windows, but in general it should work with cmd.exe.
public void TestCommandRun(){
Process process = null;
String[] command_arr = new String[]{"cmd.exe","/K","start"};
ProcessBuilder pBuilder = new ProcessBuilder("C:/Windows/System32/cmd.exe");
try{
process = pBuilder.start();
}
catch(IOException e){
e.printStackTrace();
System.out.println("Process failed");
}
if(null != process){
OutputStream out = process.getOutputStream();
OutputStreamWriter outWriter = new OutputStreamWriter(out);
BufferedWriter bWriter = new BufferedWriter(outWriter);
try{
bWriter.write("dir");
bWriter.newLine();
bWriter.write("ipconfig");
bWriter.flush();
bWriter.close();
}
catch(IOException e){
e.printStackTrace();
System.out.println("bWriter Failed");
}
}
}

How to execute a interactive shell script using java Runtime?

I am wondering is there any way to execute following shell script, which waits for user input using java's Runtime class?
#!/bin/bash
echo "Please enter your name:"
read name
echo "Welcome $name"
I am using following java code to do this task but it just shows blank console.
public class TestShellScript {
public static void main(String[] args) {
File wd = new File("/mnt/client/");
System.out.println("Working Directory: " +wd);
Process proc = null;
try {
proc = Runtime.getRuntime().exec("sudo ./test.sh", null, wd);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Thing is when I execute above program, I believed it will execute a shell script and that shell script will wait for user input, but it just prints current directory and then exits. Is there any way to do this or it is not possible at all in java?
Thanks in advance
The reason it prints the current dir and exits is because your java app exits. You need to add a (threaded) listener to the input and error streams of your created process, and you'll probably want to add a printStream to the process's output stream
example:
proc = Runtime.getRuntime().exec(cmds);
PrintStream pw = new PrintStream(proc.getOutputStream());
FetcherListener fl = new FetcherListener() {
#Override
public void fetchedMore(byte[] buf, int start, int end) {
textOut.println(new String(buf, start, end - start));
}
#Override
public void fetchedAll(byte[] buf) {
}
};
IOUtils.loadDataASync(proc.getInputStream(), fl);
IOUtils.loadDataASync(proc.getErrorStream(), fl);
String home = System.getProperty("user.home");
//System.out.println("home: " + home);
String profile = IOUtils.loadTextFile(new File(home + "/.profile"));
pw.println(profile);
pw.flush();
To run this, you will need to download my sourceforge project: http://tus.sourceforge.net/ but hopefully the code snippet is instructive enough that you can just adapt to J2SE and whatever else you are using.
If you use a Java ProcessBuilder you should be able to get the Input, Error and Output streams of the Process you create.
These streams can be used to get information coming out of the process (like prompts for input) but they can also be written to to put information into the process directly too. For instance:
InputStream stdout = process.getInputStream ();
BufferedReader reader = new BufferedReader (new InputStreamReader(stdout));
String line;
while(true){
line = reader.readLine();
//...
That'll get you the output from the process directly. I've not done it myself, but I'm pretty sure that process.getOutputStream() gives you something that can be written to directly to send input to the process.
The problem with running interactive programs, such as sudo, from Runtime.exec is that it attaches their stdin and stdout to pipes rather than the console device they need. You can make it work by redirecting the input and output to /dev/tty.
You can achieve the same behaviour using the new ProcessBuilder class, setting up the redirection using ProcessBuilder.Redirect.INHERIT.
Note sure at all you can send input to your script from Java. However I very strongly recommend to have a look at Commons Exec if you are to execute external scripts from Java:
Commons Exec homepage
Commons Exec API

Categories

Resources