我正在尝试设置一个批处理文件(当前在CMD提示符下测试),以便在目录发生更改时运行。我有一个命令存储在变量" test"它告诉我第一个音频编解码器是什么。如果它不是aa3我打算用ffmpeg重新编码音频。我的第一个问题是,当我尝试用我的var运行一个简单的if语句时,我得到一个错误。
set test=ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of default=nokey=1:noprint_wrappers=1 "my movie (2017).mkv"
当我运行%test%时,它会返回预期的内容。
如果我将其作为:
运行if %test% == "ac3" echo true
我得到:
-v was unexpected at this time.
我的最终目标是在文件夹中添加某些内容时有类似的内容(当某些内容发生变化时还没有...可能只是每天运行一次idk):
set test=ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of default=nokey=1:noprint_wrappers=1 "%f"
set outpath=S:\Blu Ray\New folder\"%f"
for %f in (*.mkv) DO
if %test% <> "ac3" (
ffmpeg -i “%f” -vcodec copy -scodec copy -acodec ac3 -b:a 640k “%outpath%";
del "%f";
move "%outpath%" "s:\Blu Ray\")
任何帮助都会很棒
BD
答案 0 :(得分:1)
命令行
if %test% == "ac3" echo true
在执行 IF 命令之前,由Windows命令解释程序进行预处理
if ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of default=nokey=1:noprint_wrappers=1 "my movie (2017).mkv" == "ac3" echo true
双引号字符串外的空格字符被解释为参数分隔符。因此,第一个参数是命令 IF ffprobe
,第二个参数是-v
,第三个参数是error
。
-v
用于命令 IF 和未知运算符,结果是错误消息:
-v此时出乎意料。
标准解决方案是双引号两个字符串进行比较,因为在双引号字符串中,空格字符以及&()[]{}^=;!'+,`~|<>
被解释为文字字符。
if "%test%" == "ac3" echo true
命令 IF 总是将双引号字符串与双引号作为字符串进行比较,并且在任何一方使用双引号时都不会运行整数比较。
但是在这种情况下使用if "%test%" == "ac3"
echo true也不能按预期工作,因为执行的命令行是:
if "ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of default=nokey=1:noprint_wrappers=1 "my movie (2017).mkv"" == "ac3" echo true
现在第一个 IF 参数为"ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of default=nokey=1:noprint_wrappers=1 "my
,第二个参数为movie
,导致出现错误消息:
此时电影出人意料。
必须使用包含分配给环境变量的双引号的字符串的延迟环境变量扩展,并使用 IF 命令与另一个字符串进行比较。
set "test=ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of default=nokey=1:noprint_wrappers=1 "my movie (2017).mkv""
setlocal EnableDelayedExpansion
if "!test!" == "ac3" echo true
endlocal
另请参阅Why is no string output with 'echo %var%' after using 'set var = text' on command line?上的答案为何使用set "test=..."
和阅读this answer有关命令 SETLOCAL 和 ENDLOCAL 的详细信息。
但是,目标是将控制台可执行文件ffprobe
的输出与字符串ac3
进行比较。
这需要使用 FOR 。
for /F "delims=" %%I in ('ffprobe.exe -v error -select_streams a:0 -show_entries stream=codec_name -of default=nokey=1:noprint_wrappers=1 "my movie (2017).mkv" 2^>^&1') do if /I "%%I" == "ac3" echo true
命令 FOR 在后台'
启动的单独命令进程中运行'
... cmd.exe /C
之间指定的命令行而不打开窗口并捕获为处理 STDOUT 而写入的所有输出,以逐行处理此输出,从而忽略空行和以分号开头的行。
2>&1
会导致ffprobe.exe
的输出被写入处理 STDERR 也会在后台命令进程中重定向,以处理 STDOUT 以便同时捕获并由 FOR 处理。
当Windows命令解释器解析整个 FOR 命令行。
我没有安装>
,因此无法测试整个 FOR 命令行。但 FOR 命令行应该可以在&
输出真正只有^
的情况下用于 STDOUT 或 STDERR 没有其他的。用双引号括起来的ffprobe.exe
的输出与ffprobe.exe
不区分大小写。
要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。
ac3
ffprobe.exe
"ac3"
endlocal /?
for /?
另请阅读Microsoft有关Using Command Redirection Operators。
的文章