Java Runime.getRuntime().exec(Cmd)命令包含单引号

人气:45 发布:2023-01-03 标签: java shell rsync

问题描述

我需要使用Java通过一个命令来同步多个文件 以下命令在外壳中运行良好 Rsync-avrz--Timeout=100 rsync://10.149.21.211:8730/‘logflow/click/file1日志流/单击/文件2’/主页/kerrycai/puler"

但当我使用以下Java代码时,它无法工作

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();

ret值不等于0(在我的测试中是5),命令执行不成功,经过调试,似乎是单引号引起的问题

所以,我的问题是

我是否可以使用Java执行包含单引号的外壳命令(请注意,单引号位于参数中间,而不是开始/结束)? 我是否可以让一个外壳命令在一个命令中rsync多个文件,并且该命令中没有单(双)引号?

推荐答案

@chris注意:在一个参数中组合多个文件名(真正修改的部分类似的文件名)确实非常不寻常,总体上对unix来说甚至是"可疑的",但对于rsync是正确的(或者至少曾经是正确的)。

前言:JavaRuntime.exec不‘执行外壳命令’(除非您显式运行外壳并给它一个命令);它运行带有参数的程序。这些不同的东西经常被混淆,因为普通用户使用的大多数外壳命令都是运行程序的命令,但这是一个差异很重要的情况。特别是,将空格引用到外壳程序会导致外壳程序向包含该空格的程序传递单个参数,而不是拆分成两个(或更多)参数,但引号本身不包括在参数中。

首先,您应该查看高级用法下的手册页(在您的系统上或在线https://download.samba.org/pub/rsync/rsync.html)。Rsync的当前(甚至是较旧的)版本有一种更方便的语法使用单独的参数来获取多个文件,Runtime.exec(String)使用的简单解析可以处理这些文件:

rsync -avrz --timeout=100 --port=8730 10.149.21.211::logflow/click/file1 ::logflow/click/file2 /home/kerrycai/puller
但是,如果您需要(或确实想要)使用带引号的形式,那么您需要自己进行标记化,并使用@EJP建议的String[]重载--尽管您仍然可以使用Runtime,但您不需要为此使用ProcessBuilder。具体地做一些类似的事情:

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); ...

14