I have a list of files for which I have to run the vimdiff command and save the output as a html file.I am doing this with Java. Below is the command I am trying to execute
String cmd = "vimdiff -c 'set foldlevel=9999' src/test/resources/testdata/output/html_output_before_changes/file1.html src/test/resources/testdata/output/html_output_after_changes/file2.html -c TOhtml -c 'w! different.html' -c 'qa!'"
When I run the below code, the code is getting executed. But I am not able to see the file getting generated.
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(cmd);
The command is running fine when executed from a terminal. But its not working when executed inside a java program. Can someone help me with this issue? I did a lot of search but not able to proceed with this.
You're using :TOhtml and write the result as different.html. If you're not sure where to locate the file, check the current working directory of the Java process, do a file search of your hard disk, or specify an absolute path in the Vim command to be sure.
You won't see anything from Vim's operation itself. Using process.getInputStream(), you could obtain what Vim wrote to the terminal during its operation, but that would just amount to a garble of characters, as Vim is using special ANSI escape sequences to control the terminal, position the cursor, etc.
To use Vim non-interactively, it is recommended to pass the following options:
-T dumb Avoids errors in case the terminal detection goes wrong.
-n No swapfile.
-i NONE Ignore the |viminfo| file (to avoid disturbing the
user's settings).
-c 'set nomore' Suppress the more-prompt when the screen is filled
with messages or output to avoid blocking.
Without a possibility to interact with Vim (from inside your Java program), a troubleshooting tip is enabling verbose logging: You can capture a full log of a Vim session with -V20vimlog. After quitting Vim, examine the vimlog log file for errors.
After Two days I found the below Solution:
I added the vimdiff command to a shell script and executed it using the following method and it worked like a gem.
Java method
try {
File[] uiDiffDir = getFiles();
for (File file : uiDiffDir) {
String[] cmd = {"sh", shellScriptPath, file1, file2,
outputfile};
Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
shell.sh
vimdiff -c 'set foldlevel=9999' $1 $2 -c TOhtml -c 'w! '"$3"'' -c 'qa!'
Note:
file1 will be passed as a argument in the place of $1
file2 will be passed as a argument in the place of $2
outputfile will be passed as a argument in the place of $3
Related
From last day, I have been trying to execute a command on Terminal (MAC) using JAVA but whatever I do nothing is working.
I have the following 2 commands that I want to execute and get the output back in JAVA
source activate abc_env
python example.py
Till now, I have tried the following methods without any output
String[] command = new String[] { "source activate abc_env", "python example.py"};
String result = executeCommands(command);
Here is my executeCommands method
private static String executeCommands(String[] command) {
StringBuffer output = new StringBuffer();
Process p;
try {
for(int i=0; i< command.length;i++)
{
p = Runtime.getRuntime().exec(command[i]);
p.waitFor();
BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
System.out.println("Error output: " + p.exitValue());
System.out.println("Output:" + output);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("Here");
}
return output.toString();
}
This gives me the following exception
Cannot run program "source": error=2, No such file or directory
I searched online and people say that source won't work like this and I should change the command to
String[] command = new String[] { "bash -c 'source activate abc_env'", "python example.py"};
Now, I donot get the exception but the command still does not work and it returns '2' as exitValue()
Then I tried to execute the commands as a script
#!/bin/bash
source activate abc_env
python example.py
I get the following exception when I read the .sh file as string and pass it to command
Cannot run program "#!/bin/bash": error=2, No such file or directory
So, my question is how to run the source command followed by python command properly through Java ? My final goal is execute some python from Java.
EDIT1:
If I try the following command and print the output stream
String[] command = {
"/bin/bash",
"-c",
"source activate cvxpy_env"
};
executeCommand(command));
Output Stream:
ExitValue:1
ErrorOutput:/bin/bash: activate: No such file or directory
If I try the same command but with single quotes around 'source activate abc_env'. I get the following output
ExitValue:127
ErrorOutput:/bin/bash: source activate cvxpy_env: command not found
Solution:
String[] command = {
"/bin/bash",
"-c",
"source /Users/pc_name/my_python_library/bin/activate abc_env;python example.py"
};
According to the Javadoc, Runtime.exec(String) breaks the command into the command-args list using a StringTokenizer, which will probably break your command into:
bash
-c
'source
activate
abc_env'
Which is obviously not what you want. What you should do is probably use the version of Runtime.exec(String[]) that accepts a ready list of arguments, passing to it new String[] {"bash", "-c", "source activate abc_env"}.
Now, to get an idea why it's not working, you should not only read from its stdout but also from stderr, using p.getErrorStream(). Just print out what you read, and it will be a great debugging aid.
Re: your edit. Now it looks like it's working fine, as far as Java and bash are concerned. The output "activate: No such file or directory" is probably the output from the successful run of the source command. It just that source can't find the activate file. Is it in the working directory? If not, you probably should have "cd /wherever/your/files/are; source activate cvxpy_env". Oh, and if your python script depends on whatever side-effects the source command has, you probably have to execute it in the same bash instance, that is:
String[] command = {
"/bin/bash",
"-c",
"cd /wherever/your/files/are && source activate cvxpy_env && python example.py"
};
Or better yet, pack it all into a single shell script, and then just Runtime.exec("./my_script.sh") (don't forget to chmod +x it, though).
Try
String[] command = {
"/bin/bash",
"-c",
"source activate abc_env; " + "python example.py"
};
I want to concatenate two dos commands in a java program. First I want to change directory then list the files and folders in that. So I wrote that like
try
{
Process process = UI.this.rt.exec("cmd.exe /c cd C:\\Users & start dir");
process.waitFor();
InputStream in = process.getInputStream();
while (in.read() != -1) {}
}
catch (Exception e)
{
System.out.println(e);
}
But this is not working. When I execute this in desktop it is not change the directory and display the files and folders which is in the desktop. Could you please help me to fix this problem? I'm using windows 7 machine.
Thanks
Isuru Liyanage
Write the commands to a batch file on the disk and execute the batch.
If you don't want to have such a batch on the disk, create it on demand and delete it after usage.
Or just use the java build-in features to list files.
EDIT
But your code works. I tried it.
It opens a dos-box an lists the directory after changing the directory.
You can use ProcessBuilder to set the working directory of the Process you exec later.
Or, do as suggested else-thread and use the Java API for listing files in a directory, which is saner.
While creating a process you can pass a string array of commands as below:
String[] command = new String[3];
command[0] = "cmd";
command[1] = "/c";
command[2] = " cd c:\\Users && dir";
Process p = Runtime.getRuntime().exec(command);
Drop the start, it runs files in a new window. Plus as there in no cmd in the NEW command DIR won't be recognised as a command. If you must use start for some reason add cmd /c to the dir part as well.
also dir c:\users is all you actually need to do. No need or reason to change directory.
The problem is that I am running a .sh file from which has 3 commands using Java's Runtime.exec("") method but only first command from .sh file gets executed.
Can anyone answer what could be the problem ?
Here is my code.
Process process = Runtime.getRuntime().exec("run.sh");
process.waitFor();
DataInputStream d = new DataInputStream(process.getInputStream());
System.out.println(d.readLine());
System.out.println("test");
run.sh script is as follows :
#! /bin/sh
echo "start"
ls -a
echo "stop"
It executes the run.sh but only first command is getting executed(echo command). I tried with different commands but result remains the same. Only first one gets executed.
DataInputStream d = new DataInputStream(process.getInputStream());
System.out.println(d.readLine());
The shell script is executing all the commands, but you are just reading the first line from the process' input stream that contains all the output of the shell script. Instead, read till the end of stream and you would see the output of all the commands.
String output = StringUtils.join(IOUtils.readLines(process.getInputStream));
Both StringUtils and IOUtils are utility classes from apache commons lang and commons IO respectively.
If you don't want to use the commons libraries, then
StringBuilder output = new StringBuilder;
String line;
while ((line = d.readLine()) != null) {
output.append(line);
}
System.out.println(output.toString());
I am running the following code, and it stops at waitfor() function. What could be the reason and how can I solve it?
String line;
Process albumProcess;
try {
albumProcess = Runtime.getRuntime().exec(
"iconv -f UTF-16 -t UTF-8 /home/gozenem/"+ xmlFileName +
".xml | grep albumID");
albumProcess.waitFor();
BufferedReader in = new BufferedReader(
new InputStreamReader(albumProcess.getInputStream()));
ArrayList<String> lineList = new ArrayList<String>();
while ((line = in.readLine()) != null) {
lineList.add(line);
}
result[0] = lineList.size();
albumProcess.destroy();
} catch (Exception e) {}
The | grep ... is not consuming the output from the command as you expect because getRuntime().exec does not understand piping symbols. The process gets bogged down waiting for something to consume its output and its getting passed bogus command line arguments "|", "grep", and "albumId".
A shell will understand | but execv will not, so you need to use bash -c instead to get a shell to do the piping (see java shell for executing/coordinating processes? do the piping yourself (see Pipe between java processes on command shell not reliable working). Java 7 has a new ProcessBuilder class that makes it easy to set up pipes so you can use those if you're only running on a bleeding edge JVM.
Once you've got grep running, if there's a bunch of lines that match, it may still fill up the buffer, so you need something sitting on the buffer consuming the process's output stream. Moving
albumProcess.waitFor();
after the while loop should do it.
I think you should try to read the output from the process before waiting on it. Otherwise, if the command outputs to much then the buffer may get filled.
Have a look at this article which explains how to read from the process: http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4
I am trying to execute a program from the Java code. Here is my code:
public static void main(String argv[]) {
try {
String line;
Process p = Runtime.getRuntime().exec(new String[]{
"/bin/bash", "-c", "executable -o filename.txt"});
BufferedReader input = new BufferedReader(
new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
}
input.close();
} catch (Exception err) {
err.printStackTrace();
}
}
My OS is Mac OS X 10.6.
Now, the executable I am trying to run is supposed to spit the output to filename.txt. If I take this command and run it on the terminal, it works fine and the filename.txt gets populated also. But, from my java program the file is not created.
if instead I use executable > filename.txt then the filename.txt is created but is empty. Not sure what's wrong here. The executable I am trying to run is Xtide (if that helps).
I would really appreciate any help I can get.
Thanks,
You cannot redirect output to file and read the output in java. It's one or the other. What you want is this:
Process p = Runtime.getRuntime().exec(new String[]{
"/bin/bash", "-c", "executable -o filename.txt"});
p.waitFor();
BufferedReader input = new BufferedReader(
new InputStreamReader(new FileInputStream("filename.txt")));
while ((line = input.readLine()) != null) {
System.out.println(line);
}
The main changes are:
p.waitFor(), since process execution is asynchronous, so you have to wait for it to complete.
The data is read from the file rather than from the output of the process (since this will be empty.)
The answer from mdma works (and I voted it up), but you might also want to consider the version where you do read the output stream directly from executable:
Process p = Runtime.getRuntime().exec(new String[]{
"/bin/bash", "-c", "executable"});
p.waitFor();
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream())_;
while ((line = input.readLine()) != null) {
System.out.println(line);
}
Correct me if I am wrong, but the symptoms are as follows:
exec("/usr/bash", "-c", "executable > filename.txt") creates an empty file.
exec("/usr/bash", "-c", "executable -o filename.txt") does not create a file.
One or both of the above gives an exit code of 255 when you look at it.
When you run the command from the command line as executable -o filename.txt or executable > filename.txt it works as expected.
In the light of the above, I think that the most likely cause is that /bin/bash is not finding the executable when you launch it from Java. The fact that the first example does create an empty file means that /bin/bash is doing something. But if you try to run
$ unknown-command > somefile.txt
from a bash shell prompt you will get an error message saying that the command cannot be found and an empty "something.txt" file. (You would not see the error message in your Java app because it is being written to stderr, and you are not capturing it.) The reason that the empty "something.txt" file is created is that it is opened by the shell before it attempts to fork and exec the "executable".
If this is the problem, then the simple solution is to use the absolute pathname for the executable.
Also, if you are not doing any command line redirection or other shell magic, there is no need to run the executable in a new bash instance. Rather, just do this:
Process p = Runtime.getRuntime().exec("executable", "-o", filename.txt");
then wait for the process to complete and check the exit code before trying to read the file contents.