向'提供Powershell参数;启动';违反命令?

向'提供Powershell参数;启动';违反命令?,powershell,Powershell,我有一个PowerShell脚本,它调用ffmpeg对当前文件夹中的所有.mp4视频文件进行两次编码 foreach ($i in Get-ChildItem . | Where { $_.extension -like ".mp4" }) { ffmpeg -y -i "$i" -c:v libx265 -b:v 2.2M -preset medium -x265-params pass=1 -an -f mkv NUL ffmpeg -i "$i" -c:v libx265 -b:v

我有一个PowerShell脚本,它调用ffmpeg对当前文件夹中的所有.mp4视频文件进行两次编码

foreach ($i in Get-ChildItem . | Where { $_.extension -like ".mp4" }) {
  ffmpeg -y -i "$i" -c:v libx265 -b:v 2.2M -preset medium -x265-params pass=1 -an -f mkv NUL
  ffmpeg -i "$i" -c:v libx265 -b:v 2.2M -x265-params pass=2 -c:a libopus -ac 1 -b:a 64k -preset medium "small\$i.mkv"
}
它工作得很好,但在使用时会使我的系统停止,所以我想给ffmpeg进程一个低优先级和一个仅允许它们使用两个CPU核的关联。所以我试着

foreach ($i in Get-ChildItem . | Where { $_.extension -like ".mp4" }) {
  start "x265ify" /wait /low /b /affinity C ffmpeg -y -i "$i" -c:v libx265 -b:v 2.1M -preset medium -x265-params pass=1 -an -f mkv NUL
  start "x265ify" /wait /low /b /affinity C ffmpeg -i "$i" -c:v libx265 -b:v 2.1M -x265-params pass=2 -c:a libopus -ac 1 -b:a 64k -preset medium "small\$i.mkv"
}
这不起作用,因为
-i
被认为是不明确的。因此,我尝试将整个命令(
“ffmpeg-y-I…”“
forward”)放在一个字符串中,引号被转义。这不起作用,因为找不到接受
/low
的位置参数。我尝试忽略这一点,将命令作为一个单独的变量传递,我尝试的任何东西似乎都不起作用

但我有一个Ruby脚本,它调用ffmpeg的方式与实际工作方式完全相同。上面写着

start "x265-ifier" /wait /low /b /affinity #{AFFINITY} ffmpeg \
              -hide_banner \
              -i "#{v}" \
              -vf scale=-2:#{HEIGHT} \
              -c:a libopus \
              -b:a #{AUDIO_BITRATE}k \
              -ac 1 \
              -c:v libx265 \
              -x265-params vbv-maxrate=#{MAX_VIDEO_BITRATE}:vbv-bufsize=7000 \
              -preset #{PRESET} \
              -crf #{CRF} \
              "#{dest}" \
              -y

那么我做错了什么?为什么PowerShell不想运行这个命令,如果Ruby是中间人,这个命令可以正常运行?为什么
/low
在文档中作为一个参数列出时不是一个参数,并且当传递给
start
的整个字符串被认为是它正在运行的命令,并且
-I
是该命令的一个有效参数时,我如何使
-I
不那么模棱两可

在PowerShell中,
start
是cmdlet[1]的内置别名,其语法和行为不同于
cmd.exe的内部
start
命令

要调用后者[1],必须显式调用
cmd.exe
,如下所示:

cmd /c start `"x265ify`" /wait /low /b /affinity C ffmpeg -y -i $i -c:v libx265 -b:v 2.1M -preset medium -x265-params pass=1 -an -f mkv NUL
注:

  • 字符
    x265ify
    被转义为
    `
    ,以确保它们被传递到
    start
    ,后者(笨拙地)使用它们来区分表示窗口标题的第一个参数与要调用的命令

  • $i
    不必双重报价,因为PowerShell会根据需要进行报价

  • 使用
    /wait
    意味着第二个
    start
    命令在第一个命令完成之前不会被调用

顺便说一句:PowerShell对空参数(
)和带有嵌入式
字符的参数的处理。从PowerShell[Core]7.0开始,传递到外部程序的参数从根本上被破坏,需要笨拙的解决方法-有关更多信息,请参阅


[1] 使用
Get命令start
来发现这个事实


[2] 这在您的情况下是必需的,因为
Start Process
不提供对已启动进程的优先级或CPU相关性的控制。

在PowerShell中,
Start
是cmdlet[1]的内置别名,其语法和行为不同于
cmd.exe
的内部
Start
命令

要调用后者[1],必须显式调用
cmd.exe
,如下所示:

cmd /c start `"x265ify`" /wait /low /b /affinity C ffmpeg -y -i $i -c:v libx265 -b:v 2.1M -preset medium -x265-params pass=1 -an -f mkv NUL
注:

  • 字符。大约
    x265ify
    被转义为
    `
    ,以确保它们被传递到
    start
    ,后者(笨拙地)使用它们来区分表示窗口标题的第一个参数和要调用的命令

  • $i
    不必双重报价,因为PowerShell会根据需要进行报价

  • 使用
    /wait
    意味着第二个
    start
    命令在第一个命令完成之前不会被调用

顺便提一下:PowerShell处理空参数(
)和嵌入
字符的参数。从PowerShell[Core]7.0开始,传递到外部程序的操作从根本上被破坏,需要笨拙的解决方法-有关更多信息,请参阅


[1] 使用
Get命令start
来发现这个事实


[2] 这在您的情况下是必要的,因为
启动进程
不能控制启动进程的优先级或CPU相关性。

很高兴听到这个消息,@GreenTriangle。请参阅我的更新,它描述了如何将命令识别为别名,以及在将参数传递给外部程序时可能出现问题的帖子链接。很高兴听到这个消息,@GreenTriangle。请参阅我的更新,它描述了如何将命令标识为别名,并链接到向外部程序传递参数时可能出现问题的帖子。