Java 执行命令在代码中不起作用
Java execute command doesn't work in code
我在我的 Java 程序中调用 java.lang.Runtime.exec(...) 来 运行 一个命令(一些 FFMPEG
命令)简单地传递给我的函数:
private static void RunCommand(String command) throws InterruptedException {
try {
// Execute command
Process proc = Runtime.getRuntime().exec(command);
}
}
运行对于简单的 FFMPEG 案例来说 ffmpeg -i input.avi -c copy output.avi
。
但是其中一个命令显然不是 运行。当我 copy/paste 命令行中的确切字符串时,我能够 运行 它并查看输出文件。
ffmpeg -i "concat:/home/temp10.avi|/home/p2.avi|/home/temp15.avi" -c copy -y /home/output.avi
代码如下:
String c4="ffmpeg -i \"concat:"+dir+temp1+"|"+dir+ad+"|"+dir+temp3+"\" -c copy -y "+dir+output;
这是怎么回事?猜猜为什么代码中没有 运行?如果 "
导致问题,为什么相应的字符串看起来不错?!
你写的命令:
ffmpeg -i "concat:/home/temp10.avi|/home/p2.avi|/home/temp15.avi" -c copy -y /home/output.avi
在 运行 被 shell 时有效。引号是 shell 语法的一部分,而不是 ffmpeg 语法的一部分。由于 |
字符,引号是必需的,这会导致 shell 在未被引号的情况下构建管道。当它被引用时,它只是传递给 ffmpeg。
您想使用 java 运行时 exec
函数完成同样的事情,但是 exec
不像 shell。它不执行管道、重定向、引用或 $variable
替换。它在 whitespace 上拆分字符串,并使用生成的字符串数组执行相当于 unix execvp
的操作。
因为 exec
不会对 |
字符做任何特殊的事情,所以不需要引用。您传递给 exec 以完成与上述 shell 命令相同的操作的字符串应该只是
ffmpeg -i concat:/home/temp10.avi|/home/p2.avi|/home/temp15.avi -c copy -y /home/output.avi
根据文件名,您可能 运行 遇到一个复杂的问题。假设您的 shell 命令如下所示:
ffmpeg -i "concat:/home/temp 10.avi|/home/p2.avi|/home/temp15.avi" -c copy -y /home/output.avi
(区别:第一个文件名 temp 10.avi
中有一个 space。)现在引用有两个目的:防止 |
创建管道,并防止space 从分裂的论点。如果您尝试将其传递给 exec
并移除引号,它将不起作用,因为字符串将被拆分,生成以下参数数组:
-i
concat:/home/temp
10.avi|/home/p2.avi|/home/temp15.avi
-c
copy
-y
/home/output.avi
这不是 ffmpeg 想要的;它需要包含完整输入规范的 -i
之后的单个字符串。您必须自己完成拆分字符串的工作,因此您可以在参数中保留 space,如下所示:
Runtime.getRuntime().exec(
new String[] {
"ffmpeg",
"-i",
"concat:/home/temp 10.avi|/home/p2.avi|/home/temp15.avi",
"-c",
"copy",
"-y",
"/home/output.avi"
}
)
下面评论中的例子看起来像
Runtime.getRuntime().exec(
new String[] {
"ffmpeg",
"-i",
"sample.mp4",
"-i",
"ad.mp4",
"-filter_complex",
"[0:v]trim=0:15,setpts=PTS-STARTPTS[v0]; [1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; [0:v]trim=20:30,setpts=PTS-STARTPTS[v2]; [v0][v1][v2]concat=n=3:v=1:a=0[out]",
"-map",
"[out]",
"output.mp4"
}
)
-filter_complex
之后的大字符串是单个参数,因为它在命令的 shell 版本中被引用。它在 shell 中的 ""
之间没有特殊字符,在 Java 中的 ""
之间没有特殊字符,因此它无需修改即可工作。
我在我的 Java 程序中调用 java.lang.Runtime.exec(...) 来 运行 一个命令(一些 FFMPEG
命令)简单地传递给我的函数:
private static void RunCommand(String command) throws InterruptedException {
try {
// Execute command
Process proc = Runtime.getRuntime().exec(command);
}
}
运行对于简单的 FFMPEG 案例来说 ffmpeg -i input.avi -c copy output.avi
。
但是其中一个命令显然不是 运行。当我 copy/paste 命令行中的确切字符串时,我能够 运行 它并查看输出文件。
ffmpeg -i "concat:/home/temp10.avi|/home/p2.avi|/home/temp15.avi" -c copy -y /home/output.avi
代码如下:
String c4="ffmpeg -i \"concat:"+dir+temp1+"|"+dir+ad+"|"+dir+temp3+"\" -c copy -y "+dir+output;
这是怎么回事?猜猜为什么代码中没有 运行?如果 "
导致问题,为什么相应的字符串看起来不错?!
你写的命令:
ffmpeg -i "concat:/home/temp10.avi|/home/p2.avi|/home/temp15.avi" -c copy -y /home/output.avi
在 运行 被 shell 时有效。引号是 shell 语法的一部分,而不是 ffmpeg 语法的一部分。由于 |
字符,引号是必需的,这会导致 shell 在未被引号的情况下构建管道。当它被引用时,它只是传递给 ffmpeg。
您想使用 java 运行时 exec
函数完成同样的事情,但是 exec
不像 shell。它不执行管道、重定向、引用或 $variable
替换。它在 whitespace 上拆分字符串,并使用生成的字符串数组执行相当于 unix execvp
的操作。
因为 exec
不会对 |
字符做任何特殊的事情,所以不需要引用。您传递给 exec 以完成与上述 shell 命令相同的操作的字符串应该只是
ffmpeg -i concat:/home/temp10.avi|/home/p2.avi|/home/temp15.avi -c copy -y /home/output.avi
根据文件名,您可能 运行 遇到一个复杂的问题。假设您的 shell 命令如下所示:
ffmpeg -i "concat:/home/temp 10.avi|/home/p2.avi|/home/temp15.avi" -c copy -y /home/output.avi
(区别:第一个文件名 temp 10.avi
中有一个 space。)现在引用有两个目的:防止 |
创建管道,并防止space 从分裂的论点。如果您尝试将其传递给 exec
并移除引号,它将不起作用,因为字符串将被拆分,生成以下参数数组:
-i
concat:/home/temp
10.avi|/home/p2.avi|/home/temp15.avi
-c
copy
-y
/home/output.avi
这不是 ffmpeg 想要的;它需要包含完整输入规范的 -i
之后的单个字符串。您必须自己完成拆分字符串的工作,因此您可以在参数中保留 space,如下所示:
Runtime.getRuntime().exec(
new String[] {
"ffmpeg",
"-i",
"concat:/home/temp 10.avi|/home/p2.avi|/home/temp15.avi",
"-c",
"copy",
"-y",
"/home/output.avi"
}
)
下面评论中的例子看起来像
Runtime.getRuntime().exec(
new String[] {
"ffmpeg",
"-i",
"sample.mp4",
"-i",
"ad.mp4",
"-filter_complex",
"[0:v]trim=0:15,setpts=PTS-STARTPTS[v0]; [1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; [0:v]trim=20:30,setpts=PTS-STARTPTS[v2]; [v0][v1][v2]concat=n=3:v=1:a=0[out]",
"-map",
"[out]",
"output.mp4"
}
)
-filter_complex
之后的大字符串是单个参数,因为它在命令的 shell 版本中被引用。它在 shell 中的 ""
之间没有特殊字符,在 Java 中的 ""
之间没有特殊字符,因此它无需修改即可工作。