Skip to the content.

执行echo someData > a.txt的命令

业务上有个需求,需要用shell命令,在java代码中执行。

第一版java代码

使用Runtime.getRuntime().exec(cmd);

String cmd = "echo someData > a.txt";
Process process = Runtime.getRuntime().exec(cmd);
process.waitFor(); //waitFor代表一直等到cmd命令执行结束,才往下执行

发现不成功,也没有相关的报错日志。
换其他方法吧

第二版java代码

使用ProcessBuilder来实现
ProcessBuilder pb = new ProcessBuilder(cmd);
Process process = pb.start();

String cmd = "echo someData > a.txt";
ProcessBuilder pb=new ProcessBuilder(cmd);
Process process = pb.start();
process.waitFor(); //waitFor代表一直等到cmd命令执行结束,才往下执行

发现不成功,但是有相关的报错日志。

Exception in thread "main" java.io.IOException: Cannot run program "echo someData > a.txt": error=2, No such file or directory

就是没有找到文件,是不是相对路径的问题,然后又弄成了绝对路径a.txt 换成 /tmp/a.txt,发现还是同样的错误。

然后百度、google,发现https://blog.csdn.net/xzw_123/article/details/46983507文章,

执行诸如:ps -ef grep -v grep 带有管道或重定向的命令就会出错。我们都知道使用以上两种方法执行命令时,如果带有参数就要把命令分割成数组或者List传入,不然会被当成一个整体执行(会出错,比如执行”ps -e”)。对于 ,<,>号来说,这样做也不行。对于Linux系统,解决方法就是把整个命令都当成sh的参数传入,用sh来执行命令。

第三版java代码

ProcessBuiler方式

//  new ProcessBuiler().command()方式
List<String> commands = Lists.newArrayList("sh", "-c", "echo someData > a.txt");
ProcessBuilder commandAdd = new ProcessBuilder().command(commands);
Process process = commandAdd.start();
process.waitFor(); //waitFor代表一直等到cmd命令执行结束,才往下执行

Runtime方式

// Runtime.getRuntime().exec()方式
String[] commands = new String[3];
commands[0] = "sh";
commands[1] = "-c";
commands[2] = "echo someData > a.txt";
Runtime.getRuntime().exec(commands).waitFor();


发现可行,也没有报错,结果也符合预期。

sh -c

image.png
从 ` -c ` 代表从字符串中读取命令

如下图:
image.png

其实本质上要解决一个awk的问题

就是计算出在a.txt中有,在b.txt中没有的数据。

awk 'NR==FNR {a[$0];next} {if (!($0 in a)) print $0}' a.txt b.txt > result.txt

awk下NR FNR的详解参考 awk NR FNR的使用