如何在 java 中的一个终端中 运行 多个带引号的命令
How to run multiple CMDs with quotes in one terminal in java
我需要在一个终端中执行 java 2 个命令,
每个命令都包含一个带空格的路径。
例如:
CMD 1:"C:\user\with space\bat1.bat"
命令 2: "C:\user\with space\bat2.bat"
目的是运行仅当CMD 1运行成功时才在同一个终端运行宁CMD 2。
我试过使用 && :
Runtime.getRuntime().exec("\"C:\user\with space\bat1.bat\" && \"C:\user\with space\bat2.bat\"");
但是我得到以下错误:
'\"C:\user\with space\bat1.bat\"' is not recognized as an internal or external command,
operable program or batch file.
我怎样才能 运行 它们并使其分别识别每个命令?
您将终端与执行混淆了。这些不是一回事。您的 OS 可以 运行 申请。终端不是“OS”。这是一个应用程序。当您在其中输入内容时,您并没有发送它 'to the system',您只是在该应用程序中输入内容。与我在 Web 浏览器中的这个文本框中键入内容没什么不同。我输入一个字母,它出现了。我按下回车键,事情发生了。
shell 对您键入的内容进行 'parsing' 的整船处理,然后使用其编写的语言相当于 Runtime.getRuntime().exec
。
有很多 /bin/bash
、/bin/zsh
、/bin/fish
、windows 的 cmd.exe
以及所有其他 shell 做。对于其中一些,确实是 OS 做到了……取决于您使用的是哪个 OS。最好绝对none依赖这些:
- 在键入非绝对路径可执行文件时搜索 PATH 以了解要 运行.2
- 追加
.exe
、.bat
、.com
或类似内容。
- 一大堆众所周知的命令,如
cd
、ls
、mkdir
等等。
&&
、||
和其他链接事物的方式。
- 文件名替换,例如
whatever.exe *.txt
(*.txt是'substitution')。1,?
也是如此。
- 变量替换,如
/bin/foo $fn
.
- 重定向管道,例如
2>/dev/null
或 <myfile.txt
。
- 通过分隔空格来拆分命令,首先考虑命令的路径和所有其他的东西,每个单独的,一个参数......但是然后查看引号,使用它们来找出某些空间不是参数之间的分隔符,当然要删除实际的引号字符。
- 将
~
替换为用户的主目录。
- 还有很多很多。
您需要全部自己完成。这就是为什么你不应该使用 Runtime.getRuntime().exec
而是总是使用 ProcessBuilder
的原因。您可以用它设置重定向,自己进行参数拆分。始终指定绝对路径。不要使用 * 或 ?对于任何事情等等。
您无法从 java 中编写一种使 2 个批处理文件不打开 2 个黑框的神奇方法。相反,创建一个新的批处理文件 运行 两个批处理文件(我认为你必须做 CALL bat1.bat
以避免出现 3 黑框),然后运行 那,你不能只 运行 批处理文件,你 运行 cmd.exe 告诉 IT 运行 批处理文件。如果非常非常简单,你可以告诉CMD一下子搞定。
Path workingDir = Paths.get(".");
List<String> batOfBatsContent = List.of(
"@ECHO OFF",
"CALL bat1.bat || GOTO :fail",
"CALL bat2.bat",
":fail");
Path megaBat = workingDir.resolve("doEverything.bat");
Files.write(megaBat, batOfBats.stream().collect(Collectors.joining("\r\n"));
ProcessBuilder pb = new ProcessBuilder();
pb.command(System.getenv("COMSPEC"), "/c", batOfBats.getAbsolutePath());
pb.start();
或者可能:
Path workingDir = Paths.get(".");
ProcessBuilder pb = new ProcessBuilder();
pb.command(System.getenv("COMSPEC"), "/c",
"\"" +
workingDir.resolve("bat1.bat").getAbsolutePath() +
"\"&&\"" +
workingDir.resolve("bat2.bat").getAbsolutePath()
+ "\"");
pb.start();
[1] 实际上,windows 可能会这样做。 Posix OS 是的(在这个时间点不是 windows 的一切)绝对不是。
[2] Java 尝试这样做,有点,但不是特别可靠。如果您不必依赖它,请不要依赖它。在任何情况下这样做在安全方面都是可疑的。
我需要在一个终端中执行 java 2 个命令, 每个命令都包含一个带空格的路径。
例如:
CMD 1:"C:\user\with space\bat1.bat"
命令 2: "C:\user\with space\bat2.bat"
目的是运行仅当CMD 1运行成功时才在同一个终端运行宁CMD 2。
我试过使用 && :
Runtime.getRuntime().exec("\"C:\user\with space\bat1.bat\" && \"C:\user\with space\bat2.bat\"");
但是我得到以下错误:
'\"C:\user\with space\bat1.bat\"' is not recognized as an internal or external command,
operable program or batch file.
我怎样才能 运行 它们并使其分别识别每个命令?
您将终端与执行混淆了。这些不是一回事。您的 OS 可以 运行 申请。终端不是“OS”。这是一个应用程序。当您在其中输入内容时,您并没有发送它 'to the system',您只是在该应用程序中输入内容。与我在 Web 浏览器中的这个文本框中键入内容没什么不同。我输入一个字母,它出现了。我按下回车键,事情发生了。
shell 对您键入的内容进行 'parsing' 的整船处理,然后使用其编写的语言相当于 Runtime.getRuntime().exec
。
有很多 /bin/bash
、/bin/zsh
、/bin/fish
、windows 的 cmd.exe
以及所有其他 shell 做。对于其中一些,确实是 OS 做到了……取决于您使用的是哪个 OS。最好绝对none依赖这些:
- 在键入非绝对路径可执行文件时搜索 PATH 以了解要 运行.2
- 追加
.exe
、.bat
、.com
或类似内容。 - 一大堆众所周知的命令,如
cd
、ls
、mkdir
等等。 &&
、||
和其他链接事物的方式。- 文件名替换,例如
whatever.exe *.txt
(*.txt是'substitution')。1,?
也是如此。 - 变量替换,如
/bin/foo $fn
. - 重定向管道,例如
2>/dev/null
或<myfile.txt
。 - 通过分隔空格来拆分命令,首先考虑命令的路径和所有其他的东西,每个单独的,一个参数......但是然后查看引号,使用它们来找出某些空间不是参数之间的分隔符,当然要删除实际的引号字符。
- 将
~
替换为用户的主目录。 - 还有很多很多。
您需要全部自己完成。这就是为什么你不应该使用 Runtime.getRuntime().exec
而是总是使用 ProcessBuilder
的原因。您可以用它设置重定向,自己进行参数拆分。始终指定绝对路径。不要使用 * 或 ?对于任何事情等等。
您无法从 java 中编写一种使 2 个批处理文件不打开 2 个黑框的神奇方法。相反,创建一个新的批处理文件 运行 两个批处理文件(我认为你必须做 CALL bat1.bat
以避免出现 3 黑框),然后运行 那,你不能只 运行 批处理文件,你 运行 cmd.exe 告诉 IT 运行 批处理文件。如果非常非常简单,你可以告诉CMD一下子搞定。
Path workingDir = Paths.get(".");
List<String> batOfBatsContent = List.of(
"@ECHO OFF",
"CALL bat1.bat || GOTO :fail",
"CALL bat2.bat",
":fail");
Path megaBat = workingDir.resolve("doEverything.bat");
Files.write(megaBat, batOfBats.stream().collect(Collectors.joining("\r\n"));
ProcessBuilder pb = new ProcessBuilder();
pb.command(System.getenv("COMSPEC"), "/c", batOfBats.getAbsolutePath());
pb.start();
或者可能:
Path workingDir = Paths.get(".");
ProcessBuilder pb = new ProcessBuilder();
pb.command(System.getenv("COMSPEC"), "/c",
"\"" +
workingDir.resolve("bat1.bat").getAbsolutePath() +
"\"&&\"" +
workingDir.resolve("bat2.bat").getAbsolutePath()
+ "\"");
pb.start();
[1] 实际上,windows 可能会这样做。 Posix OS 是的(在这个时间点不是 windows 的一切)绝对不是。
[2] Java 尝试这样做,有点,但不是特别可靠。如果您不必依赖它,请不要依赖它。在任何情况下这样做在安全方面都是可疑的。