Path names, file names via Runtime.getRunTime.exec() in Java, Windows/Linux - java

I am writing a Java Swing application in Java that serves as a frontend for the ffmpeg command. It inputs the folder and the file name from the user and adds many more parameters that are constantly displayed in JTextField. User can edit the final command in the text field that it about to be called.
This works in both Windows and Linux:
Process ffmpeg = Runtime.getRuntime().exec(command, null, new File(current_working_folder));
command is a string. It is formatted depending from the OS, so that the path is always given in full (absolute path) and the slashes are appropriate for the given OS.
In Windows and Linux, it is possible to execute ffmpeg command by enclosing the folder and file names in "....". In Windows, this formatting ultimately works through Runtime.getRunTime.exec().
However, in Linux, this does not work through Runtime.getRunTime.exec(). The quotation marks are perhaps misunderstood "....".
Any advice on this?

Try passing your command as an array, rather than a string using this method: Runtime.exec(String[] cmdarray, String[] envp, File dir).
For example, instead of :
Runtime.getRuntime().exec("ffmpeg -i video_origine.avi video_finale.mpg", null, new File(current_working_folder));
use:
Runtime.getRuntime().exec(new String[]{"ffmpeg", "-i", "video_origine.avi", "video_finale.mpg"}, null, new File(current_working_folder));

Related

Call easy_install apps from java with ProcessBuilder/RunTime

The title doesn't really explain my question, but I don't know how to ask it in a better way. So, basicly, I'm writing a app that uses the program livestreamer. I installed it on my mac using: easy_install -U livestreamer . So far, so good, it works when I write livestream on my terminal. Now, my issue is that when I try to call it on java:
public static void runLiveStreamer(String channel, String quality) throws IOException{
String[] cmd = new String[]{"livestreamer", "twitch.tv/"+channel, quality};
Process proc = Runtime.getRuntime().exec(cmd);
InputStreamReader isr = new InputStreamReader(proc.getInputStream());
BufferedReader br = new BufferedReader(isr);
String line=null;
while ( (line = br.readLine()) != null)
System.out.println(line);
}
I get this error:
Exception in thread "main" java.io.IOException: Cannot run program "livestreamer": error=2, No such file or directory
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1128)
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1071)
at java.base/java.lang.Runtime.exec(Runtime.java:591)
at java.base/java.lang.Runtime.exec(Runtime.java:450)
at livestream.runLiveStreamer(livestream.java:12)
I know the code works, because if I replace the String[] cmd = new String[]{"livestreamer", "twitch.tv/"+channel, quality}; with, for example, ls, it outputs without any problem. This is my first time messing with this kinds of stuff, so my error is probably a really newbie one. Thanks in advance for all the help!
livestreamer is not in your Java process’s path.
Every Windows and Unix operating system’s execution environment has a concept of a program path. The path is an environment variable (named PATH in all operating systems except Windows, which uses Path). It contains a list of directories, separated by colons :, except on Windows where they’re separated by semicolons (;).
As with any environment variable, each running process may have its own path defined, and child processes usually inherit it from their parent process.
Whenever you try to run a program without any directory separators (for instance, trying to run ls instead of /bin/ls), the system will look for that program in each directory in the path.
In your terminal, your PATH contains a directory which has livestream in it. When you run your Java process, you have a different PATH, one which does not include the directory which contains livestream.
The easiest solution is to refer to livestream by its absolute file name, thus making the system execution path irrelevant:
String[] cmd = { "/usr/bin/livestreamer", "twitch.tv/" + channel, quality };
/usr/bin/livestreamer is just an example. I don’t know where livestreamer was actually installed on your system.
To find it, do which livestreamer in your terminal. That should tell you the absolute location of it. (I think in Windows, the command would be where livestreamer.)

Passing a path to exec

I am trying to use the exec function. The path to the executable contains spaces and this is giving me grief
My code looks like this
Runtime.getRuntime().exec("\"C:\\Program Files (x86)\\ASL\\_ASL Software Suite_installation.exe\"", null, new File("\"C:\\Program Files (x86)\\ASL\\_ASL Software Suite_installation\""));
When this is executed I get an exception -
Cannot run program ""c:\Program"
I would be grateful if someone can give me some help in solving this
Thanks in advance
From Runtime.exec(String command, String[] envp, File dir):
Executes the specified string command in a separate process with the specified environment and working directory.
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.
This means the first string is broken into tokens, regardless of the outer quotes. Use the Runtime.exec(String[] cmdarray, String[] envp, File dir) version to avoid the tokenization of the executable path.
Or, use ProcessBuilder:
File d = new File("C:/Program Files (x86)/ASL/_ASL Software Suite_installation");
ProcessBuilder pb = new ProcessBuilder(d.getAbsolutePath() + "/main.exe");
Process p = pb.directory(d)
.start();
See:
Why should avoid using Runtime.exec() in java?
ProcessBuilder vs Runtime.exec()
You don't need to quote the filenames again. Java will take care of it for you just give the proper filename as a string like so
Runtime.getRuntime().exec(
"C:\\Program Files (x86)\\ASL\\_ASL Software Suite_installation.exe",
null,
new File("C:\\Program Files (x86)\\ASL\\_ASL Software Suite_installation"));

How to run bat file from java with arguments (i.e file name with full path) having folder name with space

Am trying to execute the a bat file with some arguments through a JAVA programmes . the arguments are file name with full path, And this path had some folder name with space, which are creating issue and giving me the following error
Error: 'D:\Documents' is not recognized as an internal or external
command
the code is as below
String command = "D:\Documents and Settings\ A.bat" + " " D:\Documents and Settings\B.xml
1. process = Runtime.getRuntime().exec(new String[] {"cmd.exe","/c",command});
2. process.waitFor();
3. exitValue = process.exitValue();
You need to escape the \ in your string (i.e. doubling them: D:\\Documents), but that is not the problem. You can try to escape the spaces Documents\\ and\\ Settings or you use the exec method that does this for you. Just dont build the command line by yourself. Better use ProcessBuilder for starting processes.
String command = "\"D:\Documents and Settings\\" A.bat" + " \"D:\Documents and Settings\B.xml\""
Escape double quotes, so you can include double quotes in the literal, to give:
cmd.exe /x "D:\Documents and Settings\" A.bat "D:\Documents and Settings\B.xml"
I was trying to do the same thing. I googled whole day but didn't make it work. At Last I handled it in this way, I am sharing it if it comes to any use of anybody :
String command = "A.bat D:\\Documents and Settings\\B.xml";
File commandDir = new File ( "D:\\Documents and Settings ");
String[] cmdArray = { "cmd.exe", "/c", command };
1. Process process = Runtime.getRuntime().exec( cmdArray, null, cmdArray );
2. process.waitFor();
3. exitValue = process.exitValue();
I've spent a while searching on SO and the wider Internet and was about to post this as a new question when I came across this, which does seem identical to my issue...
I am trying to call a Windows batch file from Java. The batch file takes several arguments but just the first, which is a path to a data file, is of relevance to this problem. The cut-down command line that I have been experimenting with is essentially:
cmd /c c:\path\to\my\batchfile.bat c:\path\to\my\datafile.mdl
I'm using Apache Commons Exec which ultimately delegates to Runtime.getRuntime().exec(String[] cmdarray, String[] envp, File dir), the 'correct' version as opposed to the overloaded versions taking a single String command. Quoting of the arguments when they contain spaces is therefore taken care of.
Now, both the path to the batch file and/or the path to the data file can have spaces in them. If either the path to the batch file or the path to the data file have spaces in, then the batch file is executed. But if both have spaces in them then the path to the batch file is truncated at the first space.
This has to be a (Java or Windows?) bug, right? I've debugged right down to the native call to create() in java.lang.ProcessImpl and all seems ok. I'm on JDK1.6.

Java command Runtime.getRuntime().exec() in Mac OS

I´m using Mac OS Lion, with java version 1.6.0_26
I'm making a small app for Mac in Java with a main menu for the user, so he can choose several options.
One of them is install an app using a .pkg
Everything was working fine with these commands:
File instFolder = new File(System.getProperty("user.dir") + "/foldername/appInstaller.pkg");
String s = "open "+ instFolder.toString();
Process p = Runtime.getRuntime().exec(s);
Then I realized that there is a problem when foldername has spaces or if I copy this java file with the needed subfolders to a USB pen drive with "NO NAME" as name (or some name with spaces).
Because s will become something like:
open /Volumes/NO NAME/foldername/appInstaller.pkg
or
open /Users/user1/Desktop/folder name/appInstaller.pkg
So when you run the p process, the command will finish where the first space appears on the path
open /Volumes/NO
or
open /Users/user1/Desktop/folder
To try to fix this I changed the s definition for something like this:
String s = "open "+ "\"" + instFolder.toString() + "\"";
It stopped working fine. The strange thing is that if i copy the s value (after creating the s variable) and paste it in the terminal it works:
open "/Users/user1/Desktop/folder name/appInstaller.pkg"
but running it from Java it does't work.
Could you help me, please?
Thanks.
In order to properly escape arguments, you can use the following:
Runtime.getRuntime().exec(new String[] { "open", instFolder.toString() });
Though I would probably to use the more modern ProcessBuilder:
ProcessBuilder pb = new ProcessBuilder("open", instFolder.toString());
Process p = pb.start();
int exitCode = p.waitFor();
Though this may be worth a read depending on what you want to do with the processes output.
Note: edited to reflect question in comment
it seems your path does not have quotes when turned into the shell.
You should probably add "'" on both sides of your path, so the final shell command will look like:
open 'your path'
instead of
open your path
Here's a little trick that came out from the answers mentioned above:
ProcessBuilder pb = new ProcessBuilder(commandString.split(" "));
Say commandString = "killall Mail" then the split will separate the words making it a String[] parameter to the ProcessBuilder.

Compressing and Archiving the files in the folder using Java Runtime

I am trying to Compress and Archive all the files in a folder, using Java Runtime class. My code snippet looks as this :
public static void compressFileRuntime() throws IOException, InterruptedException {
String date = Util.getDateAsString("yyyy-MM-dd");
Runtime rt = Runtime.getRuntime();
String archivedFile = "myuserData"+date+".tar.bz2";
String command = "tar --remove-files -cjvf "+archivedFile+" marketData*";
File f = new File("/home/amit/Documents/");
Process pr = rt.exec(command, null, f);
System.out.println("Exit value: "+pr.exitValue());
}
The above code doesn't archive and compress the file as expected, though it creates a file myuserData2009-11-18.tar.bz2 in the folder "/home/amit/Documents/".
Also the output is
Exit value: 2.
While if I execute the same command from command line, it gives the expected result.
Please tell me what I am missing.
Thanks
Amit
The problem lies in this part:
" marketData*"
you expect the filenames to be compressed to be globbed from the * wildcard. Globbing is done by the shell, not by the tools themselves. your choices are to either:
numerate the files to be archived yourself
start the shell to perform the command ("/bin/sh -c")
start tar on the folder containing the files to be archived
Edit:
For the shell option, your command would look like:
String command = "sh -c \"tar --remove-files -cjvf "+archivedFile+" marketData*\"";
(mind the \"s that delimit the command to be executed by the shell, don't use single quotes ot the shell won't interpret the glob.)
If really you want to create a bzip2 archive, I'd use a Java implementation instead of a native command which is good for portability, for example the one available at http://www.kohsuke.org/bzip2/ (it is not really optimized though, compression seems to be slower than with Java LZMA).

Categories