How to execute unix commands through Windows/cygwin using Java How to execute unix commands through Windows/cygwin using Java unix unix

How to execute unix commands through Windows/cygwin using Java


1. Calling unix commands:

You simply need to call your unix shell (e.g. the bash delivered with cygwin) instead of cmd.

bash -c "ls -la"

should do. Of course, if your command is an external program, you could simply call it directly:

ls -la

When starting this from Java, it is best to use the variant which takes a string array, as thenyou don't have Java let it parse to see where the arguments start and stop:

Process p =      Runtime.getRuntime().exec(new String[]{"C:\\cygwin\\bin\\bash.exe",                                            "-c", "ls -la"},                               new String[]{"PATH=/cygdrive/c/cygwin/bin"});

The error message in your example (ls: command not found) seems to show that your bash can't find the ls command. Maybe you need to put it into the PATH variable (see above for a way to do this from Java).

Maybe instead of /cygdrive/c/cygwin/bin, the right directory name would be /usr/bin.

(Everything is a bit complicated here by having to bridge between Unix and Windows conventions everywhere.)

The simple ls command can be called like this:

Process p = Runtime.getRuntime().exec(new String[]{"C:\\cygwin\\bin\\ls.exe", "-la"});

2. Invoking multiple commands:

There are basically two ways of invoking multiple commands in one shell:

  • passing them all at once to the shell; or
  • passing them interactively to the shell.

For the first way, simply give multiple commands as argument to the -c option, separated by ; or \n (a newline), like this:

bash -c "cd /bin/ ; ls -la"

or from Java (adapting the example above):

Process p =      Runtime.getRuntime().exec(new String[]{"C:\\cygwin\\bin\\bash.exe",                                            "-c", "cd /bin/; ls -la"},                               new String[]{"PATH=/cygdrive/c/cygwin/bin"});

Here the shell will parse the command line as, and execute it as a script. If it contains multiple commands, they will all be executed, if the shell does not somehow exit before for some reason (like an exit command). (I'm not sure if the Windows cmd does work in a similar way. Please test and report.)

Instead of passing the bash (or cmd or whatever shell you are using) the commands on thecommand line, you can pass them via the Process' input stream.

  • A shell started in "input mode" (e.g. one which got neither the -c option nor a shell script file argument) will read input from the stream, and interpret the first line as a command (or several ones).
  • Then it will execute this command. The command itself might read more input from the stream, if it wants.
  • Then the shell will read the next line, interpret it as a command, and execute.
  • (In some cases the shell has to read more than one line, for example for long strings or composed commands like if or loops.)
  • This will go on until either the end of the stream (e.g. stream.close() at your side) or executing an explicit exit command (or some other reasons to exit).

Here would be an example for this:

Process p = Runtime.getRuntime().exec(new String[]{"C:\\cygwin\\bin\\bash.exe", "-s"});InputStream outStream = p.getInputStream(); // normal output of the shellInputStream errStream = p.getInputStream(); // error output of the shell// TODO: start separate threads to read these streamsPrintStream ps = new PrintStream(p.getOutputStream());ps.println("cd /bin/");ps.println("ls -la");ps.println("exit");ps.close();


You do not need cygwin here. There are several pure Java libraries implementing SSH protocol. Use them. BTW they will solve your second problem. You will open session and execute command withing the same session, so the shell state will be preserved automatically.

One example would be JSch.