Search code examples
javashellcp

java using shell commands


So trying to use "cp" to copy a file from one location to another - the file is denominated with a file name containing white space ("test test"). When invoking command in the shell (bash) it works fine, but called from java it fails. I use escape characters. Code:

import java.io.*;

public class Test {

  private static String shellify(String path) {
    String ret = path;
    System.out.println("shellify got: " + ret);
    ret = ret.replace​(" ", "\\ ");
    System.out.println("shellify returns: " + ret);
    return ret;
  }    

  private static boolean copy(String source, String target) {
    String the_command = ""; // will be global later
    boolean ret = false;
    try {
      Runtime rt = Runtime.getRuntime();
      String source_sh = shellify(source);
      String target_sh = shellify(target);
      the_command = new String
    ("cp -vf " + source_sh + " " + target_sh);
      System.out.println("copy execing: " + the_command);
      Process p = rt.exec(the_command);
      InputStream is = p.getInputStream();
      BufferedReader br = new BufferedReader
    (new InputStreamReader(is));
      String reply = br.readLine();
      System.out.println("Outcome; " + reply);
      ret = (reply != null) && reply.contains("->");
    } catch(Exception e) {
      System.out.println(e.getMessage());
    }
    the_command = "";
    return ret;
  }

  public static void main(String[] args) {
    String source = "test1/test test";
    String target = "test2/test test";
    if(copy(source, target))
      System.out.println("Copy was successful");
    else
      System.out.println("Copy failed");
  }

}

...and the outcome is this

shellify got: test1/test test
shellify returns: test1/test\ test
shellify got: test2/test test
shellify returns: test2/test\ test
copy execing: cp -vf test1/test\ test test2/test\ test
Outcome; null
Copy failed

whereas if I use bash the copy succeeded (big surprise).

Sino-Logic-IV:bildbackup dr_xemacs$ cp -vf test1/test\ test test2/test\ test
test1/test test -> test2/test test

Can anyone please tell me why this is? Copying files without white spaces works just fine.

/dr_xemacs


Solution

  • You should pass the arguments individually and they do not need escaping in shellify because the String[] version of exec provides each argument to the script separately as one argument even if they contain spaces:

    String[]the_command = new String[] {"cp","-vf", source, target);
    

    You may need to fix PATH available to Java VM if cp is not present in one of the PATH directories, or you could fully qualify the path to the executable cp in the_command [0].

    Your code is missing a line to check the cp / process exit code, add waitFor after consuming the STDOUT / getInputStream():

    int rc = p.waitFor();