File copy using getRuntime().exec() - java

I am trying to copy a file. Here is the source. Note, des is string variable containing the URL.
Process process = Runtime.getRuntime().
exec("cmd.exe\t/c\tcopy\t"+source+"\t"+des);
Can anyone tell me why it does not work?

I think you should use FileUtils.copyFile() but anyways try this.
String[] command = new String[5];
command[0] = "cmd";
command[1] = "/c";
command[2] = "copy";
command[3] = "test.java";
command[4] = "D:";
Process p = Runtime.getRuntime().exec (command);
Instead of passing your command as a single string construct an array and than pass it to exec.
I tried this
String command = "cmd /c copy test.java D:";
worked fine for me.

Advice:
Use ProcessBuilder to construct the Process.
That automatically takes care of '2' - break the command into parts.
Merge the output streams (not entirely necessary, but makes it simpler to ..).
Consume (and display) the output streams.
But in general, read and implement all the recommendations of When Runtime.exec() won't.

Runtime.exec, I believe, send the string to the command processor cmd.exe. So this is running cmd.exe, running another cmd.exe inside it, and passing your arguments. I don't have a Windows machine to test it on (thank Gods) but I think there are arguments to cmd.exe to tell it to run the arguments as a command line.

Why not just use FileUtils.copyFile()?

Related

Pipe ("|") doesn't work with ProcessBuilder in Android [duplicate]

I'm trying to use Java's ProcessBuilder class to execute a command that has a pipe in it. For example:
ls -l | grep foo
However, I get an error:
ls: |: no such file or directory
Followed by:
ls: grep: no such file or directory
Even though that command works perfectly from the command line, I can not get ProcessBuilder to execute a command that redirects its output to another.
Is there any way to accomplish this?
This should work:
ProcessBuilder b = new ProcessBuilder("/bin/sh", "-c", "ls -l| grep foo");
To execute a pipeline, you have to invoke a shell, and then run your commands inside that shell.
The simplest way is to invoke the shell with the command line as the parameter. After all, it's the shell which is interpreting "|" to mean "pipe the data between two processes".
Alternatively, you could launch each process separately, and read from the standard output of "ls -l", writing the data to the standard input of "grep" in your example.
Since Java 9, there’s genuine support for piplines in ProcessBuilder.
So you can use
List<String> result;
List<Process> processes = ProcessBuilder.startPipeline(List.of(
new ProcessBuilder("ls", "-l")
.inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE),
new ProcessBuilder("grep", "foo")
.redirectError(ProcessBuilder.Redirect.INHERIT)
));
try(Scanner s = new Scanner(processes.get(processes.size() - 1).getInputStream())) {
result = s.useDelimiter("\\R").tokens().toList();
}
to get the matching lines in a list.
Or, for Windows
List<String> result;
List<Process> processes = ProcessBuilder.startPipeline(List.of(
new ProcessBuilder("cmd", "/c", "dir")
.inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE),
new ProcessBuilder("find", "\"foo\"")
.redirectError(ProcessBuilder.Redirect.INHERIT)
));
try(Scanner s = new Scanner(processes.get(processes.size() - 1).getInputStream())) {
result = s.useDelimiter("\\R").tokens().toList();
}
These examples redirect stdin of the first process and all error streams to inherit, to use the same as the Java process.
You can also call .redirectOutput(ProcessBuilder.Redirect.INHERIT) on the ProcessBuilder of the last process, to print the results directly to the console (or wherever stdout has been redirected to).

How to run commands you can run on terminal in Java

So guys I want to execute a command that you can execute on the cmd in my Java program. After doing some study, I thought i found a way to do this. However, my code doesn't work.
My code is
import java.io.*;
public class CmdTest {
public static void main(String[] args) throws Exception {
String[] command = {"ag","startTimes conf.js >> pro.txt"};
ProcessBuilder builder = new ProcessBuilder(command);
builder.directory(new File("./test-java/"));
Process p = builder.start();
}
}
The program executes but produces no output. I tried using other commands like "ls -a", but still no output.
Can someone please help me debug this or suggest a better way of doing this? Thank you
Edit 1: I am executing this on a Mac. If that is necessary for debugging
Edit 2: The usual ls and other commands are working with the solutions that you guys have provided. I however want to use the ag (the_silver_searcher) command in the Java program. When i try that, i get the following error -
Exception in thread "main" java.io.IOException: Cannot run program "ag startTimes conf.js >> pro.txt": error=2, No such file or directory
The existing answers give you the information on how to solve your problem in code, but they don't give a reason why your code is not working.
When you execute a program on a shell, there's significant processing done by the shell, before the program is ever executed. Your command line
String[] command = {"ag","startTimes conf.js >> pro.txt"};
ProcessBuilder builder = new ProcessBuilder(command);
assumes that the command ag is run with the single argument startTimes conf.js >> pro.txt - most likely not what you want to do. Let's go one step further: What if you wrote
String[] command = {"ag","startTimes", "conf.js", ">>", "pro.txt"};
ProcessBuilder builder = new ProcessBuilder(command);
?
This would assume that the ag command knows about the >> parameter to redirect its output - and here is where the shell comes into play: The >> operator is an instruction to the shell, telling it what to do with the output from stdout of the process. The process ag, when started by the shell, never has an idea of this redirection and has no clue about >> and the target file name at all.
With this information, just use the code samples from any of the other answers. I won't copy them into mine for proper attribution.
While there is ProcessBuilder, I've always used Runtime.getRuntime().exec("cmd");
Process Runtime.exec(String)
It returns a Process which you can get the input and output streams of
Even if you stay with the ProcessBuilder, you should still have access to the Process.get<Input/Output/Error>Stream()
You need to read the output of the process by opening an input stream from the process:
try (BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())) {
System.out.println(reader.readLine()); // process the output stream somehow
}
Additionally you might the read the error stream ( p.getErrorStream()), which I often have done in a separate stream, in Java 8 you can use redirectErrorStream(true) on the ProcessBuilder to automatically add the error stream to the input stream. Of course you can't distinquish anymore from which stream the input comes, but it makes reading easier. If you don't read the input or error stream and the process's buffer becomes full the processes tend to pause until there is enough room in the buffer again.
You can also add
builder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
before the start method which redirects the output to the console.
//"ls" command runs under the "sh" on linux(cmd.exe on windows), so first arg is "sh"
//second arg "-c" tells "sh" which exact command should be executed
//"ls" is actual command
//"startTimes" as I understand is a file or directory, it is arg for "ls" command
//"conf.js" is second arg for "ls" command
new ProcessBuilder("sh", "-c", "ls", "startTimes", "conf.js")
//set working dir for "sh" process"
.directory(new File("./test-java/"))
//output will be written to "pro.txt" in working dir of "sh" process
.redirectOutput(new File("./test-java/pro.txt"))
.start();

sending command to terminal from java with space in it

I am working on a java program, where i need to invoke a bash script that takes a string as an argument. so I've written the code:
Process p = Runtime.getRuntime().exec("./script \"message send\"");
but it seems as if the terminal isn't recognizing the quotes (") as quotes, and referring to the term "message send" as two arguments: "message and send", and so the script is not invoked properly.
anyone have any idea what i can do?
You can perform this by using ProcessBuilder.
ProcessBuilder processBuilder = new ProcessBuilder();
p.command("cmd_to_run", "args_if_any");
p.start();

Call external exe multiple times one after another

I am calling an external exe using the following commands:
String bat_file = "cmd /c start out.bat";
Process p= Runtime.getRuntime().exec(bat_file);
The problem is that I need to call the specific exe multiple times but one after another(the next exe starts after the previous exe is finished). They can not run simultaneously as they access the same files.
I tried to use a for but is not working.
Any ideas?
The problem in your approach is basically the start command. It creates a separate process. If you remove it, you can successfully use waitFor:
String batchFile = "cmd /c out.bat";
Process p = Runtime.getRuntime().exec(batchFile);
int resultCode = p.waitFor();
thank you. I finally solved it using
String batchFile = "cmd /c start/wait out.bat";

Java execute a command with a space in the pathname

How can I execute a Java System (shell) command that has a space in the pathname?
I've tried putting quotes and a backslash (), But it does not work.
ln -s "dir1/dir2" "my\ dir/dir2"
By far the most reliable way is to use Runtime.exec(String[] cmdarray).
If you use Runtime.exec(String command), Java only splits the command on whitespace.
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.
See also g++: File not found
Or use ProcessBuilder something like this:
ProcessBuilder pb = new ProcessBuilder("ln", "-s", "dir1/dir2", "my dir/dir2");
Process p = pb.start();
Do you really need to execute it in a shell (e.g. do you need to shell expansion of things like ~ or *, etc)? If not, you could invoke ln directly:
Process p =
Runtime.getRuntime()
.exec(new String[]{"/bin/ln","-s","dir1/dir2", "my\\ dir/dir2"});
If you really need a shell, try this (this may need a little tweaking depending on how the shell processes the quotes):
Process p =
Runtime.getRuntime()
.exec(new String[]{"/bin/sh", "-c", "ln -s \"dir1/dir2\" \"my\\ dir/dir2\""});
Edit:
I was under the impression the second path has a literal backslash in it. If it's not supposed to remove the \\ from the string literals above.
None of these work on Lion. However, the following does work, and is backwards compatible for Tiger.
Runtime.getRuntime().exec(new String[]{"/bin/bash","-c","/path/to/file/space*init"});
You can use it in the following way without having to introduce any backslashes:
Runtime.getRuntime().exec(new String[]{"ln", "-s", "dir1/dir2", "my dir/dir2"});

Categories

Resources