Am trying to pop up a CMD then execute some Commands such as:
echo SOMETHING && echo SOMETHING && mkdir....etc
i managed to open the CMD but JAVA doesnt seem to recognize "&" inside string
the first command which before the "&" is the only being executed
any tips ?
try {
// Execute command
String command = "cmd /c start echo hello baby & echo the world";
Process child = Runtime.getRuntime().exec(command);
// Get output stream to write from it
} catch (IOException e) {
}
}
}
It's &&, not &.
A double ampersand is a logical "and", a single ampersand means "put the (first!) process into the background".
PS: By "cmd", do you mean the good ol' Windows cmd.exe? If yes, I don't know if those ampersands are working there. Try the PowerShell instead if so.
Related
I try to execute a shell command via java like this
if (Program.isPlatformLinux())
{
exec = "/bin/bash -c xdg-open \"" + file.getAbsolutePath() + "\"";
exec2 = "xdg-open \"" + file.getAbsolutePath() + "\"";
System.out.println(exec);
}
else
{
//other code
}
Runtime.getRuntime().exec(exec);
Runtime.getRuntime().exec(exec2);
but nothing happens at all. When I execute this code it prints /bin/bash -c xdg-open "/home/user/Desktop/file.txt" in the console, but does not open the file. I have also tried to call the bash first and then the xdg-open-command, but there is not change.
What's the problem here and how can I solve this?
EDIT: The output of the calling looks like this:
xdg-open "/home/user/Desktop/files/einf in a- und b/allg fil/ref.txt"
xdg-open: unexpected argument 'in'
But this seeems very strange to me - why is the command seperatet before the in even the entire path is set in quotation marks?
Please note that you don't need xdg-open to do this.
You can use the java platform-agnostic Desktop API:
if(Desktop.isDesktopSupported()) {
Desktop.open("/path/to/file.txt");
}
Update
If the standard approach still gives issues, you can pass the parameters as an array since Runtime.exec does not invoke a shell and therefore does not support or allow quoting or escaping:
String program;
if (Program.isPlatformLinux())
{
program = "xdg-open";
} else {
program = "something else";
}
Runtime.getRuntime().exec(new String[]{program, file.getAbsolutePath()});
I got stuck trying to run a compound shell command from a Groovy script. It was one of those commands where you separate with "&&" so that the 2nd command never runs if the 1st one fails. For whatever reason I couldn't get it to work. I was using:
println "custom-cmd -a https://someurl/path && other-cmd -f parameter".execute([], new File('/some/dir')).text
The shell kept misinterpreting the command throwing errors like "custom-cmd -f invalid option" It was like it was ignoring the "&&" in between. I tried using a semi-colon as well but was not lucky. I tried using straight Java APIs Runtime.getRuntime().exec() and splitting the command into an array. I tried wrapping the command in single quotes and giving it to '/bin/sh -c' but nothing works.
How do you run a compound shell command from Java? I know I've done this in the past but I cannot figure it out today.
With groovy, the list form of execute should work:
def out = ['bash', '-c', "custom-cmd -a https://someurl/path && other-cmd -f parameter"].execute([], new File('/some/dir')).text
Of course you may want to use the consumeProcessOutput method on process, as if the output is too large, calling text may block
Try something like:
Runtime.getRuntime().exec("cmd /c \"start somefile.bat && start other.bat && cd C:\\test && test.exe\"");
Runtime.getRuntime().exec() can be used without splitting the commands into an array.
see https://stackoverflow.com/a/18867097/1410671
EDIT:
Have you tried using a ProcessBuilder? This seems to work on my OSX box:
public static void main(String[] args) throws IOException {
ProcessBuilder builder = new ProcessBuilder( "/bin/sh", "-c", "echo '123' && ls" );
Process p=null;
try {
p = builder.start();
}
catch (IOException e) {
System.out.println(e);
}
Scanner s = new Scanner( p.getInputStream() );
while (s.hasNext())
{
System.out.println( s.next() );
}
s.close();
}
I'm trying to use a redirect in a command executed with the exec()-method of java.lang.Runtime on Ubuntu 14.04
public static void main(String[] args) throws IOException, Exception {
Runtime runtime = Runtime.getRuntime();
String command = "echo bla > bla.txt";
System.out.println("Command : " + command);
Process process = runtime.exec(command);
printLines(" stdout", process.getInputStream());
printLines(" error", process.getErrorStream());
process.waitFor();
System.out.println("ExitValue : " + process.exitValue());
}
private static void printLines(String name, InputStream ins) throws Exception {
try(Stream<String> lines = new BufferedReader(new InputStreamReader(ins)).lines()) {
lines.forEach(line -> System.out.println(name + " : " + line));
}
}
The output is:
Command : echo bla > bla.txt
stdout : bla > bla.txt
ExitValue : 0
So bla > bla.txt is written to stdout but of course there is no redirect to bla.txt.
Perhapes shell redirects are not possible in a simple exec().
So I tried to change the command = "/bin/bash -c 'echo bla > bla.txt'" to use the whole echo and redirect as a parameter to /bin/bash.
With this I get the result:
Command : /bin/bash -c 'echo bla > bla.txt'
error : bla: -c: line 0: unexpected EOF while looking for matching `''
error : bla: -c: line 1: syntax error: unexpected end of file
ExitValue : 1
Of course /bin/bash -c 'echo bla > bla.txt'works fine on Ubuntu and creates the desired file.
I found no place where I could set the single quotes to get a satisfying result, and I also tried with all kinds of escape characters to escape the spaces or the redirect (>).
It works if I use a command array like
String cmdArray[] = {"/bin/bash", "-c", "echo bla > bla.txt"};
Process process = runtime.exec(cmdArray);
, but it has to be a single string because the entire command has to be build somewhere else.
I surely know
that there are better ways to write strings to files,
that it may be a bad idea to execute commands build somewhere else,
and so on ...
I'm just curious why this does not work.
The cause is that exec uses simple StringTokenizer with any white space as a delimiter to parse the actual command. Therefore it's portable as it does work nowhere when you pass something complex :-)
The workaround you chose is correct way, portable and most of all safest asyou ddon't need to escape if the command contained for example quotes etc.
String command = "echo bla > bla.txt";
Process process = runtime.exec(command);
The > blah.txt text in your command is shell syntax to redirect standard output. It's implemented by shells like sh or bash.
Runtime.exec() doesn't use a shell to run commands. The way it launches commands is described here and here. Basically, it uses its own logic to split the command string into arguments at spaces, then directly executes the resulting command.
If you want to invoke a command which should be interpreted as a shell command, you need to explicitly invoke a shell:
String[] command = { "/bin/bash", "-c", "echo bla > bla.txt" };
Process process = runtime.exec(command);
I have a perl script that needs 2 arguments to be run. I am currently using Ubuntu and I managed to execute the perl script from terminal by changing directory to where the perl script exists and by writing
perl tool.pl config=../mydefault.config file=../Test
However, when I am trying to run the perl script from my java program (I am using eclipse), It always gives me the message Command Failure. This is the code :
Process process;
try {
process = Runtime.getRuntime().exec("perl /home/Leen/Desktop/Tools/bin/tool.pl config=../mydefault.config file=../Test");
process.waitFor();
if(process.exitValue() == 0) {
System.out.println("Command Successful");
} else {
System.out.println("Command Failure");
}
} catch(Exception e) {
System.out.println("Exception: "+ e.toString());
}
So please what is wrong in my code?
You should be separating the command from it's arguments in the call to exec(), such as:
Runtime.getRuntime().exec(new String[] {"perl", "/home/Leen...", "config=...", "file=..."});
With what you currently have, Runtime is looked for a command literally named perl /home/Leen/Desktop..., spaces and all.
When you run the whole command from the Terminal, your shell is smart enough to realize that a space delimits the name of the command (perl) from the arguments that should be passed to it (/home/Leen/Desktop..., config=..., file=...). Runtime.exec() is not that smart.
I am facing a weird issue with executing a system command from JAVA code.
Actually i want to get the Mac OSX system information from my JAVA App.
For that im using
Runtime.getRuntime().exec("system_profiler -detailLevel full");
This is working fine.If i print the output,it is cool.
But i want to write this information to a plist file for future use.For that im using the -xml argument of system_profiler.like,
String cmd = "system_profiler -detailLevel full -xml > "+System.getProperty( "user.home" )+"/sysinfo.plist";
Process p = Runtime.getRuntime().exec(cmd);
Basically this should create a plist file in the current users home directory.
But this seems to be not writing anything to file.
Am i missing something here ?
My Java is more than rusty, so please be gentle. ;-)
Runtime.exec() does not automatically use the shell to execute the command you passed, so the IO redirection is not doing anything.
If you just use:
"/bin/sh -c system_profiler -detailLevel full > path/file.plist"
Then the string will be tokenized into:
{ "/bin/sh", "-c", "system_profiler", "-detailLevel", "full", ">", "path/file.plist" }
Which also wouldn't work, because -c only expects a single argument.
Try this instead:
String[] cmd = { "/bin/sh", "-c", "system_profiler -detailLevel full > path/file.plist" };
Process p = Runtime.getRuntime.exec(cmd);
Of course, you could also just read the output of your Process instance using Process.getInputStream() and write that into the file you want; thus skip the shell, IO redirection, etc. altogether.
Christian.K is absolutely correct. Here is a complete example:
public class Hello {
static public void main (String[] args) {
try {
String[] cmds = {
"/bin/sh", "-c", "ls -l *.java | tee tmp.out"};
Process p = Runtime.getRuntime().exec (cmds);
p.waitFor ();
System.out.println ("Done.");
}
catch (Exception e) {
System.out.println ("Err: " + e.getMessage());
}
}
}
If you weren't using a pipe (|) or redirect (>), then you'd be OK with String cmd = "ls -l *.java", as in your original command.
If you actually wanted to see any of the output in your Java console window, then you'd ALSO need to call Process.getInputStream().
Here's a good link:
Running system commands in Java applications