1

I need to use Java to rsync several files using one command the following command works fine in shell rsync -avrz --timeout=100 rsync://10.149.21.211:8730/'logflow/click/file1 logflow/click/file2' /home/kerrycai/puller"

but when i use the following Java code , it does not work

String cmd = "rsync -avrz --timeout=100 rsync://10.149.21.211:8730/'logflow/click/file1 logflow/click/file2' /home/kerrycai/puller";
Process p = Runtime.getRuntime().exec(cmd);
int ret =  p.waitFor();

the ret value is not equal to 0 (5 in my test), and the command is not executed succeed, after some debugging , it seem the problem is caused by the single quote

So, my questions is

  1. Can I using java to execute a shell command which has single quote in it (Pls note, the single quote is in the middle of a parameter, not start/end) ?
  2. Can I have a shell command to rsync several files in one command , and the command does not have single(double) quotes in it ?
YichaoCai
  • 71
  • 1
  • 4
  • Try without the single quotes at all... Nothing requires single quotes here. Do you realize that at the command line, `'l'\s` and `ls` are the same? If you don't believe me, try it... – fge Mar 04 '16 at 04:52
  • This single quote is deeply suspicious: is the intent to combine `logflow/click/file1 logflow/click/file2` into one large path? That seems incorrect... – Chris Kitching Mar 04 '16 at 04:55
  • Try it with the `ProcessBuilder` and the overload that takes a `String[]`. It isn't clear that the single quotes are necessary at all. – user207421 Mar 04 '16 at 05:13

2 Answers2

3

Note to @Chris: this combination of multiple filenames (really modified-partly-like-filenames) in one argument is indeed very unusual and even 'suspicious' for Unix in general, but is (or at least was) correct for rsync in particular.

Preface: Java Runtime.exec does NOT 'execute a shell command' (unless you explicitly run a shell and give it a command); it runs a program, with arguments. These different things are often confused because most of the shell commands used by normal users are commands to run programs, but this is one case where the difference matters. In particular quoting a space to shell causes the shell to pass a single argument to the program containing the space instead of splitting into two (or more) arguments, but the quote itself is NOT included in the argument.

First you should look at the man page (on your system or online at https://download.samba.org/pub/rsync/rsync.html) under ADVANCED USAGE. Current (and IME even moderately old) versions of rsync have a more convenient syntax with separate arguments to get multiple files, which the simple parsing used by Runtime.exec(String) can handle like this:

rsync -avrz --timeout=100 --port=8730 10.149.21.211::logflow/click/file1 ::logflow/click/file2 /home/kerrycai/puller

But if you need (or really want) to use the quoted-space form then you need to do the tokenization yourself and use the String[] overload as suggested by @EJP -- although you can still use Runtime, you don't need ProcessBuilder for this. Specifically do something along the lines of:

String[] cmdarray = {"rsync",
    "-avrz",
    "--timeout=100",
    "rsync://10.149.21.211:8730/logflow/click/file1 logfile/click/file2",
    // separated argument contains space but not single (or other) quote
    "/home/kerrycai/puller" };
... Runtime.getRuntime.exec(cmdarray); ...
dave_thompson_085
  • 34,712
  • 6
  • 50
  • 70
0

You're calling a somewhat large command from Java. Why not just use a shell script? Put your gnarly command in myScript.sh and then have Java invoke /bin/bash myScript.sh. Makes all the weirdness to do with string handling in Java go away.

Chris Kitching
  • 2,559
  • 23
  • 37
  • the rsync filenames is generated using other java dinamic, it will be much more complicated if i first store the command, and then using Java to invoke the shell file – YichaoCai Mar 04 '16 at 05:02
  • Well, that's what I get for trying to cheat. As fge remarked in a comment, it is unclear if you actually need these quotes. Looking at it, I'm not sure they're achieving anything except possibly causing two of your URLs to be combined in a dubious way. In any case, in Java, a string does not need any special treatment to contain a single quote: http://stackoverflow.com/questions/16664090/in-java-should-i-escape-a-single-quotation-mark-in-string-double-quoted – Chris Kitching Mar 04 '16 at 05:07