From 4d7b4da46a280d299995e0a90c2a80307fdad322 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 4 Jun 2021 18:36:18 +0800 Subject: [PATCH] fix space bug --- CHANGELOG.md | 3 +- .../java/cn/hutool/core/util/RuntimeUtil.java | 109 +++++++++++++----- .../cn/hutool/core/util/RuntimeUtilTest.java | 2 +- 3 files changed, 85 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51547fef5..ed571b6a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------------------------------------- -# 5.6.7 (2021-06-03) +# 5.6.7 (2021-06-04) ### 🐣新特性 * 【core 】 CharSequenceUtil增加join重载(issue#I3TFJ5@Gitee) @@ -13,6 +13,7 @@ ### 🐞Bug修复 * 【core 】 修复FileUtil.normalize去掉末尾空格问题(issue#1603@Github) * 【core 】 修复CharsetDetector流关闭问题(issue#1603@Github) +* 【core 】 修复RuntimeUtil.exec引号内空格被切分的问题(issue#I3UAYB@Gitee) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/util/RuntimeUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/RuntimeUtil.java index 1d417ad36..3703f8702 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/RuntimeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/RuntimeUtil.java @@ -2,6 +2,8 @@ package cn.hutool.core.util; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.lang.Console; +import cn.hutool.core.text.StrBuilder; import java.io.File; import java.io.IOException; @@ -9,6 +11,7 @@ import java.io.InputStream; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; +import java.util.Stack; /** * 系统运行时工具类,用于执行系统命令的工具 @@ -74,22 +77,9 @@ public class RuntimeUtil { * @return {@link Process} */ public static Process exec(String... cmds) { - if (ArrayUtil.isEmpty(cmds)) { - throw new NullPointerException("Command is empty !"); - } - - // 单条命令的情况 - if (1 == cmds.length) { - final String cmd = cmds[0]; - if (StrUtil.isBlank(cmd)) { - throw new NullPointerException("Command is empty !"); - } - cmds = StrUtil.splitToArray(cmd, StrUtil.C_SPACE); - } - Process process; try { - process = new ProcessBuilder(cmds).redirectErrorStream(true).start(); + process = new ProcessBuilder(handleCmds(cmds)).redirectErrorStream(true).start(); } catch (IOException e) { throw new IORuntimeException(e); } @@ -120,20 +110,8 @@ public class RuntimeUtil { * @since 4.1.6 */ public static Process exec(String[] envp, File dir, String... cmds) { - if (ArrayUtil.isEmpty(cmds)) { - throw new NullPointerException("Command is empty !"); - } - - // 单条命令的情况 - if (1 == cmds.length) { - final String cmd = cmds[0]; - if (StrUtil.isBlank(cmd)) { - throw new NullPointerException("Command is empty !"); - } - cmds = StrUtil.splitToArray(cmd, StrUtil.C_SPACE); - } try { - return Runtime.getRuntime().exec(cmds, envp, dir); + return Runtime.getRuntime().exec(handleCmds(cmds), envp, dir); } catch (IOException e) { throw new IORuntimeException(e); } @@ -301,4 +279,81 @@ public class RuntimeUtil { public static long getUsableMemory() { return getMaxMemory() - getTotalMemory() + getFreeMemory(); } + + /** + * 处理命令,多行命令原样返回,单行命令拆分处理 + * @param cmds 命令 + * @return 处理后的命令 + */ + private static String[] handleCmds(String... cmds){ + if (ArrayUtil.isEmpty(cmds)) { + throw new NullPointerException("Command is empty !"); + } + + // 单条命令的情况 + if (1 == cmds.length) { + final String cmd = cmds[0]; + if (StrUtil.isBlank(cmd)) { + throw new NullPointerException("Command is blank !"); + } + cmds = cmdSplit(cmd); + Console.log(cmds); + } + return cmds; + } + + /** + * 命令分割,使用空格分割,考虑双引号和单引号的情况 + * + * @param cmd 命令,如 git commit -m 'test commit' + * @return 分割后的命令 + */ + private static String[] cmdSplit(String cmd){ + final List cmds = new ArrayList<>(); + + final int length = cmd.length(); + final Stack stack = new Stack<>(); + boolean inWrap = false; + final StrBuilder cache = StrUtil.strBuilder(); + + char c; + for (int i = 0; i < length; i++) { + c = cmd.charAt(i); + switch (c){ + case CharUtil.SINGLE_QUOTE: + case CharUtil.DOUBLE_QUOTES: + if(inWrap){ + if(c == stack.peek()){ + //结束包装 + stack.pop(); + inWrap = false; + } + cache.append(c); + } else{ + stack.push(c); + cache.append(c); + inWrap = true; + } + break; + case CharUtil.SPACE: + if(inWrap){ + // 处于包装内 + cache.append(c); + } else{ + cmds.add(cache.toString()); + cache.reset(); + } + break; + default: + cache.append(c); + break; + } + } + + if(cache.hasContent()){ + cmds.add(cache.toString()); + } + + return cmds.toArray(new String[0]); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/util/RuntimeUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/RuntimeUtilTest.java index 98fcd9969..662542d15 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/RuntimeUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/RuntimeUtilTest.java @@ -29,7 +29,7 @@ public class RuntimeUtilTest { @Test @Ignore public void execCmdTest2() { - String str = RuntimeUtil.execForStr("cmd /c cd C:\\Program Files (x86)"); + String str = RuntimeUtil.execForStr("cmd /c", "cd \"C:\\Program Files (x86)\"", "chdir"); Console.log(str); }