I need to copy files of specific pattern from one director to another
File Pattern: "nm.cdr.*(asterisk)-2014-08-16-14*(asterisk).gz"
Command: "cp " + inputPath + filesPattern + " " + destPath;
If i use specific file instead of using * than it works fine(for single file) but with pattern using * it doesn't work.
Edit 1: I tried following code:
public void runtimeExec(String cmd)
{
StringBuffer output = new StringBuffer();
Process p;
try
{
p = Runtime.getRuntime().exec(cmd);
p.waitFor();
BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
}
catch (IOException | InterruptedException e)
{
LogProperties.log.error(e);
}
}
The asterisk is something interpreted by the shell, so you need to use the shell as the main process, the command line for the process in Java would be something like bash -c '/origin/path/nm.cdr.*-2014-08-16-14*.gz /destination/path'.
Now, if you try to use this command in a single string it won't work, you need to use a String[] instead of a String. So you need to do the following:
1: change your method's signature to use a String[]:
public void runtimeExec(String[] cmd)
2: call your method with this value for cmd:
String[] cmd = new String[] {"bash", "-c",
"cp " + imputPath + filesPattern + " " + destPath};
Can't see what exactly is passed as a command, but on linux often is necessary to split command and parameters to string array, like:
String[] cmd = {"cp", inputPath+filesPattern, destPath};
Related
I have a program called darknet. It's a C-program made from Darknet.
I want to run the darknet program in a folder Darknet that looks like this:
I'm going to run darknet with Java Process Builder, but I get no responce from it when I run this code:
// Arguments
String darknetNamePath = darknet.getValue().getFilePath().replace("Darknet/", "./");
String configurationFlag = configuration.getValue().getFilePath().replace("Darknet/", "");
String weightsFlag = weights.getValue().getFilePath().replace("Darknet/", "");
String imageFlag = "data/cameraSnap.png";
String thresholdFlag = "-thresh " + thresholds.getValue();
// Process builder
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.directory(new File("Darknet")); // We need to stand inside the folder "Darknet"
String commandString = "detect " + configurationFlag + " " + weightsFlag + " " + imageFlag + " " + thresholdFlag;
System.out.println("darknetNamePath = " + darknetNamePath);
System.out.println("commandString = " + commandString);
processBuilder.command(darknetNamePath, commandString);
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("\nExited with error code : " + exitCode);
Here is my output. Why doesn't it work for me?
darknetNamePath = ./darknet
commandString = detect cfg/yolov2-tiny.cfg weights/yolov2-tiny.weights data/cameraSnap.png -thresh 0.8
Exited with error code : 0
But when I call darknet file via terminal, then it works.
./darknet detect cfg/yolov2-tiny.cfg weights/yolov2-tiny.weights data/cameraSnap.png -thresh 0.6
UPDATE 2:
Here is my update.
// Arguments
String darknetNamePath = darknet.getValue().getFile().getAbsolutePath();
String configurationFlag = configuration.getValue().getFilePath().replace("Darknet/", "");
String weightsFlag = weights.getValue().getFilePath().replace("Darknet/", "");
String imageFlag = "data/cameraSnap.png";
String thresholdFlag = "-thresh " + thresholds.getValue();
// Process builder
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command(darknetNamePath, "detect", configurationFlag, weightsFlag, imageFlag, thresholdFlag);
Process process = processBuilder.start();
if (process.getInputStream().read() == -1) {
System.out.println(darknetNamePath);
System.out.println("detect");
System.out.println(configurationFlag);
System.out.println(weightsFlag);
System.out.println(imageFlag);
System.out.println(thresholdFlag);
System.out.printf("ERROR!");
}
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("\nExited with error code : " + exitCode);
Output:
/home/dell/Dokument/GitHub/Vaadin-DL4J-YOLO-Camera-Mail-Reporter/Vaadin-DL4J-YOLO-Camera-Mail-Reporter/Darknet/darknet
detect
cfg/yolov2-tiny.cfg
weights/yolov2-tiny.weights
data/cameraSnap.png
-thresh 0.3
ERROR!
Exited with error code : 0
UPDATE 3:
This works:
// Arguments
String darkPath = darknet.getValue().getFilePath().replace("Darknet/", "./"); // We need to call ./darknet, not absolute path
String configurationFlag = configuration.getValue().getFilePath().replace("Darknet/", "");
String weightsFlag = weights.getValue().getFilePath().replace("Darknet/", "");
String imageFlag = "data/camera.png";
String thresValue = String.valueOf(thresholds.getValue());
// Process builder
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.directory(new File("Darknet")); // Important
processBuilder.command(darkPath, "detect", configurationFlag, weightsFlag, imageFlag, "-thresh", thresValue);
processBuilder.redirectErrorStream(true); // Important
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("\nExited with error code : " + exitCode);
Your command must break all arguments into separate pieces - including thresholdFlag. It is a good idea to check if the executable exists. If it does not you should check where it is located or fix your Path variable to ensure that it can be located:
File darkpath = new File(darknetNamePath);
String [] cmd = new String[] { darkpath.getAbsolutePath(), "detect", configurationFlag, weightsFlag, imageFlag, "-thresh", String.valueOf(thresholds.getValue()) };
System.out.println("Path: "+darkpath+ " exists="+darkpath.exists());
System.out.println("exec "+Arrays.toString(cmd));
processBuilder.command(cmd);
It is also worth handling STDERR, the easiest way is to redirect STDERR=>STDOUT before calling processBuilder.start()
processBuilder.redirectErrorStream(true);
If you want Java to launch the executable without prefixing the absolute path it needs to be in one of these directories:
System.out.println("PATH COMPONENTS FOR JAVA LAUNCH:");
Arrays.asList(System.getenv("PATH").split(File.pathSeparator)).forEach(System.out::println);
You are using ProcessBuilder the wrong way. The command method takes a executable and arguments as separate strings, not a path and then another string with the actual command and all its arguments. There is no shell involved to do word splitting on the command, so you pass all your distinct arguments as one argument.
I don't have darknet, so here's a simple command using the Unix echo command:
import java.io.*;
public class ProcessBuilderTest {
public static void main(String[] args) throws Exception {
ProcessBuilder processBuilder = new ProcessBuilder();
String[] command = {"/bin/echo", "hello", "world"};
processBuilder.command(command);
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("Exited with error code : " + exitCode);
}
}
When I run this, I get:
robert#saaz:~$ java ProcessBuilderTest.java
hello world
Exited with error code : 0
It's not clear to my why your command doesn't produce an error. If I give a bad command (e.g., a trailing space behind "echo"), I get an exception:
Exception in thread "main" java.io.IOException: Cannot run program "/bin/echo ": error=2, No such file or directory
This may be OS specific. Or maybe you have some other darknet executable that gets picked up.
I am trying to run a command to read a string from a file inside a remote address (and I'm sure the file is there), this command works when I run it on the bash but it doesn't work when I run it in my java code.
Runtime rt = Runtime.getRuntime();
String[] command;
String line;
try {
command = new String[] {"sh", "-c", "\"sshpass " + "-p " + password + " ssh " + user + "#" + ip + " 'cat " + file.getAbsolutePath() + "'\"" };
Process mountProcess = rt.exec(command);
mountProcess.waitFor();
bufferedReader = new BufferedReader(new InputStreamReader(mountProcess.getInputStream()));
while ((line = bufferedReader.readLine()) != null) {
user_list.put(user, line);
}
bufferedReader.close();
bufferedReader = new BufferedReader(new InputStreamReader(mountProcess.getErrorStream()));
while ((line = bufferedReader.readLine()) != null) {
LOGGER.debug("Stderr: " + line);
}
bufferedReader.close();
} catch ...
No line is added to my user_list (so the line from getInputStream is null) and I get the following error from the logger in the code:
Stderr: sh: 1: sshpass: not found
If I use the exact same command on the bash it works and it prints the string I need.
sshpass -p password ssh remote#192.168.1.10 'cat /home/ID/ID'
Anyone knows why this is happening? thanks!
I'd suggest you don't need to use sh to wrap your command. Try
command = new String[] {"sshpass", "-p", password, "ssh", user + "#" + ip, "cat " + file.getAbsolutePath() };
If you need to use sh, then remove the escaped double quotes from the command string: you are sending those as literal characters:
command = new String[] {
"sh",
"-c",
String.format("sshpass -p %s ssh %s#%s 'cat %s'", password, user, ip, file.getAbsolutionPath())
};
If you're still getting "command not found", then you need to either specify the full path to sshpass, or ensure that its directory is in your PATH.
When doing this command with java the user is tomcat8 instead of root (when used in the bash terminal)
The solution that worked for me included some flags:
String.format("/usr/local/bin/sshpass -p %s /usr/bin/ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no %s#%s 'cat %s'", password, user, ip, file.getAbsolutePath());
I am running my Java program from terminal and I am trying to count the number of files in a certain directory using a linux command in my code; I have managed to get output for all other commands but this one.
My command is: ls somePath/*.xml | wc -l
When I run my command in my code, it appears that it has nothing to output, yet when I run the same exact command in terminal it works just fine and actually outputs the number of xml files in that directory.
Here is my code:
private String executeTerminalCommand(String command) {
String s, lastOutput = "";
Process p;
try {
p = Runtime.getRuntime().exec(command);
BufferedReader br = new BufferedReader(
new InputStreamReader(p.getInputStream()));
System.out.println("Executing command: " + command);
while ((s = br.readLine()) != null){//it appears that it never enters this loop since I never see anything outputted
System.out.println(s);
lastOutput = s;
}
p.waitFor();
p.destroy();
} catch (Exception e) {
e.printStackTrace();
}
return lastOutput;//returns empty string ""
}
Updated code w/ output
private String executeTerminalCommand(String command) {
String s, lastOutput = "";
try {
Process p = new ProcessBuilder().command("/bin/bash", "-c", command).inheritIO().start();
//Process p = Runtime.getRuntime().exec(command);
BufferedReader br = new BufferedReader(
new InputStreamReader(p.getInputStream()));
System.out.println("Executing command: " + command);
while ((s = br.readLine()) != null){
System.out.println("OUTPUT: " + s);
lastOutput = s;
}
System.out.println("Done with command------------------------");
p.waitFor();
p.destroy();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("LAST OUTPUT IS: " + lastOutput);
return lastOutput;
}
output:
Executing command: find my/path -empty -type f | wc -l
Done with command------------------------
1
LAST OUTPUT IS:
To execute a pipeline, you have to invoke a shell, and then run your commands inside that shell.
Process p = new ProcessBuilder().command("bash", "-c", command).start();
bash invokes a shell to execute your command and -c means commands are read from string. So, you don't have to send the command as an array in ProcessBuilder.
But if you want to use Runtime then
String[] cmd = {"bash" , "-c" , command};
Process p = Runtime.getRuntime().exec(cmd);
Note: You can check advantages of ProcessBuilder here and features here over Runtime
When I execute the below command on command line, it shows all the stored procedures and tables in the sybase DB.
printf 'sp_help\ngo\n' | isql -Uxx -Pxxxx -Dxxxxx
But when I do the same thing in java. This does not return any result.
Can anyone tell me what is the problem with my code below:
public class test
{
public static void main(String[] args)
{
String cmd = "printf "+"\'sp_help\ngo\n\'"+"| isql -Uxx -Pxxxx -Dxxxxx" ;
try{
Process p;
p = Runtime.getRuntime().exec(cmd);
p.waitFor();
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = reader.readLine())!=null){
System.out.println("Row is :" + line);
} catch(Exception e)
{
System.out.println("Exception Caught : " + e);
}
}
}
EDIT
I executed it as below suggested by Darkdust but still it doesnt work.
try{
Process p;
p = Runtime.getRuntime().exec("sh -c \'printf \"sp_help\ngo\n\" | isql -Uxx -Pxxxxx -Dxxxxxx\'");
p.waitFor();
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = reader.readLine())!=null){
System.out.println("Row is :" + line);
}
}
catch(Exception e)
{
System.out.println("Exception Caught : " + e);
}
But the command :
sh -c 'printf "sp_help\ngo\n" | isql -Usa -Psybase11 -Dcnadb'
Works on command line.
I also tried with :
p = Runtime.getRuntime().exec(new String[]{"sh","-c","\'printf \"sp_help\ngo\n\"","|isql -Uxx -Pxxxxx -Dxxxxx\'"});
But with no sucess.
Several things come to mind:
Incomplete PATH environment variable (thus isql can't be found).
If it's a command you provide, instead of messing with PATH you might want to make sure your are you in the correct working directory and call ./isql instead.
Since you're using a pipe, you should let a shell execute this as in sh -c "foo | bar". Otherwise the | isql ... part is passed as argument to printf as well.
I am trying to run "tar -ztf /users/home/test.tar.gz | head -1" in Java, which worked when I tried to run it in unix command line directly.
The result of this command will list one line of the file/folder inside of the test.tar.gz.
for example: proj/test/test_dir
But I when I run it in java. it will give this error:
Running command: tar -ztf /users/home/test.tar.gz | head -1
[java] tar: Options `-[0-7][lmh]' not supported by *this* tar
[java] Try `tar --help' for more information.
Any idea what's wrong with it? why is it related to "specify drive and density" option?
The code I have run:
String s = null;
StringBuffer sbOutput = new StringBuffer();
StringBuffer errorInfo = new StringBuffer();
String[] cmd = {"tar", "-ztf", fileName, "|", "head", "-1"};
try
{
Runtime rt = Runtime.getRuntime();
System.out.println("Running command: " + cmd[0] + " " + cmd[1] + " " + cmd[2] + " " + cmd[3] + " " + cmd[4] + " " + cmd[5]);
Process p = rt.exec(cmd);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
//If there is an error - only show that
while ((s = stdError.readLine()) != null)
{
errorInfo.append(s + "\n");
}
if (errorInfo.length() > 0)
{
System.out.println(errorInfo.toString());
}
while ((s = stdInput.readLine()) != null) {
sbOutput.append(s + "\n");
}
// wait for end of command execution
try {
p.waitFor();
} catch (InterruptedException ie) {
new LogErrThread(ie).start();
ie.printStackTrace();
}
p.destroy();
if (sbOutput.length() > 0)
{
System.out.println(sbOutput.toString());
}
}
catch (IOException e)
{
new LogErrThread(e).start();
e.printStackTrace();
}
On the command line, the shell is doing the piping for you. Only the arguments before the | are passed to gtar. Your code incorrectly passes the pipe and the rest of the text as arguments to gtar.
Luckily, the solution is simple. You can simply read the first line yourself.
String[] cmd = {"gtar", "-ztf", fileName};
// ...
// Instead of current input loop.
s = stdInput.readLine();
if(s != null) {
sbOutput.append(s + "\n");
}
while (stdInput.readLine() != null) {
// Disregard. Reading to end to prevent hang.
}
To elaborate Matthew's point, the | operator is interpreted by the shell. To run your command without the shell, you would need to launch the programs separately and connect their pipes together (tricky in Java).
If you input is sanitized, you can invoke the shell and give it the command to run. Its the easier approach, though arguably less portable. In general, the SHELL environment variable contains the user's shell. Shells also have a defacto standardized -c option to pass them a command string in argv. If you invoke $SHELL -c [command string], you should get the behavior you want.