Shell (bash) brace expansion with Java's runtime.exec - java

I'm trying to get an expansion command to work with runtime.exec, but the braces are being interpreted as literals rather than being expanded. Here's what I'm trying to do:
String command = "mkdir -p Foldername{1,2,3}/InnerFolder";
Runtime.getRuntime().exec( new String[] { "sh", "-c", command } );
Unfortunately, that gives me a single folder in my current directory named "Foldername{1,2,3}" instead of "Foldername1", "Foldername2", and "Foldername3". Does anyone know of a way to prevent the braces from being interpreted as literals?

You're trying to use Bash wildcards. They are interpreted within the Bash shell. You are running mkdir directly, so there is no shell to interpret {}. You need to specify path to the shell
String command = "mkdir -p Foldername{1,2,3}/InnerFolder";
Runtime.getRuntime().exec( new String[] { "/bin/bash", "-c", command } );
Source.

Related

Using 'cmd /c dir' vs 'dir'

Using the method
public Process exec(String command, String[] envp, File dir) throws IOException
I am supposed to print the output of the command dir [filepath] but using Java,
and my question is, why do I have to type for the command argument, (cmd /c dir), and not just (dir)?
If I type dir [filepath] in command prompt for Windows, it works, but not in Java.
exec() executes new process, and for that you need executable file to run (i.e. some .exe file, if we talk about Windows). But there is no "dir.exe". "dir" is built-in command of the Windows Command Prompt, cmd.exe, so to run it, you need to run cmd.exe and pass such command to it.
In contrast, for example, in Linux, ls is separate executable, so there you can directly do something like ls /home/myuser instead of sh -c 'ls /home/myuser'.

Java runtime exec zip command with "*" character

I want to zip contents of folder without including folder it self using Java Runtime
For example: zip folder /home/duyvt/example
In terminal, I exec the following commands and it works well. Archive.zip will include only contents of example folder.
$ cd /home/duyvt/example.
$ zip -r /home/duyvt/archive.zip *
But in Java Runtime, it does not work.
Runtime.getRuntime().exec("zip -r /home/duyvt/archive.zip *", null, new File("/home/duyvt/example"));
It seems Java Runtime does not understand "*" character.
I have also tried to use "ProcessBuilder" but not work too.
Is there anyone can help me ?.
Thanks for any help.
On Linux, it is the shell that understands and expands *.
On Windows, the command program has to do it itself.
Java is generic, and does not implement shell functionality.
If you want shell functionality, run the command through the shell, e.g.
sh -c 'zip -r /home/duyvt/archive.zip *'
UPDATE
From javadoc of exec(String command, String[] envp, File dir):
This is a convenience method. An invocation of the form exec(command, envp, dir) behaves in exactly the same way as the invocation exec(cmdarray, envp, dir), where cmdarray is an array of all the tokens in command.
More precisely, the command string is broken into tokens using a StringTokenizer created by the call new StringTokenizer(command) with no further modification of the character categories. The tokens produced by the tokenizer are then placed in the new string array cmdarray, in the same order.
Since StringTokenizer doesn't understand the shell quoting using '', the command is split incorrectly, and you'll have to do it yourself:
Runtime.getRuntime().exec(new String[] { "sh",
"-c",
"zip -r /home/duyvt/archive.zip *" },
null, new File("/home/duyvt/example"));
Start shell and pass it a command, like so:
"sh -c 'zip -r /home/duyvt/archive.zip *'"

How to add command to Linux shell after we open it from window command prompt?

I want to access linux shell and put command into it from my CMD(command prompt) windows.
Below is my code to open linux shell from cmd.
Runtime.getRuntime().exec(new String[] {"cmd", "/c", "start", "accessLinux.bat"});
I have try putting command after accessLinux.bat, but the compiler will join my accesLinux.bat and argument1 as one statement instead of treat it seperately eventhough i have put double quote.
Runtime.getRuntime().exec(new String[] {"cmd", "/c", "start", "\""accessLinux.bat argument1 + "\""});
below is my accesslinux.bat
#echo off
set PATH=C:\;%PATH%
set CYGWIN=binmode tty
set TERM=ansi
set USERNAME=user
set HOME=C:\
set RSYNC_RSH=ssh.exe
ssh -o StrictHostKeyChecking=no user#address %1
Base on MadProgramer comment
Runtime.getRuntime().exec(new String[] {"cmd", "/c", "start", accessLinux.bat, argument1});

How to use linux commands involving ">" through runTime.exec()

I'm new to Java. I want to use a command
"ps -e > /home/root/workspace/MyProject/ProcessList.txt"
with runTime.exec();
On searching through the web, I came to know that runTime.exec() doesn't support pipes or redirecting. Please let me know how can I execute this command with my Java code. Please give exact answers.
Pipes and redirection are features provided by the shell. The easy (and dirty) solution is to spawn the command inside a shell: "/bin/sh -c 'ps -e > /home/root/workspace/MyProject/ProcessList.txt'".
Edit: I had forgotten that the default StringTokenizer does not work with quoted strings. Provide arguments as an array of strings.
String[] args = {
"/bin/sh",
"-c",
"ps -e > /home/root/workspace/MyProject/ProcessList.txt"
};
java.lang.Runtime.getRuntime(args);
You could take a look at this question: Input and Output Stream Pipe in Java
Otherwise, if you know you are on a platform that supports the bourne shell (sh), you could add that to the command to run the original command in that shell:
"sh -c 'ps -e > /home/root/workspace/MyProject/ProcessList.txt'"

Having problems running system commands from a java program:

This is giving just the output of ls:
String[] cmd={"bash","-c","ls","-l"}:
ProcessBuilder pb=new ProcessBuilder(cmd);
Whereas this is giving long listing output properly:
String[] cmd={"bash","-c","ls -l"};
In the first code snippet, the -l option is being passed as an argument to bash, and not to ls. Bash interprets the -l option as specifying that it should behave as a 'login' shell.
The argument after -c should include the whole bash script (spaces included) that you want to be executed, so the second code snippet is correct.
The former passes two option flags to bash: -c with argument ls, and -l which according to the manpage causes bash to act as a login shell.
The second passes one option flag, -c, which the argument ls -l as a single string.
String[] cmd={"bash","-c","ls -l"}:
ProcessBuilder pb=new ProcessBuilder(cmd);
The arguements are to bash, so if you want bash to interpert your "command" via "bash", "-c", ...
then the next item needs to be your entire command, aka "ls -l".
Bash will then parse up the "command" and the -l will be sent as a parameter to "ls". Currently it is a parameter to "bash", which is why you're not getting the results you desire.

Categories