使用 echo 将 youtube-dl 的输出管道输出到使用 ffmpeg 的脚本看起来不错,但是 returns 执行时出错

Piping output of youtube-dl to a script using ffmpeg looks ok using echo but returns an error when executing

我正在尝试使用 youtube-dl 获取一些视频的网址,然后将生成的网址通过管道传输到我的脚本的输入中。所以在我的终端我做

youtube-dl --ignore-config -iga ~/Desktop/youtube/videolist.txt | myscript.sh

在我的脚本中,我将事物定义为

command='ffmpeg'        
inputArgs='-i'              
outputArgs='-c:v libx264 -preset ultrafast -qp 0'       
directory="${HOME}/Desktop/Videos/"
output="video${count}"      
extension='mp4'         

我用 echo 测试它以确保所有内容都以正确的顺序出现。

echo "${command}" "${inputArgs}" "${input}" "${outputArgs}" \
"${directory}""${output}${count}"."${extension}"

而且输出看起来是正确的。但是当我在没有前面的 echo 命令的情况下尝试 运行 相同的东西时,即

"${command}" "${inputArgs}" "${input}" "${outputArgs}" \
"${directory}""${output}${count}"."${extension}"

我收到一条错误消息说

At least one output file must be specified.

所以对我来说很明显我在尝试执行它时做错了什么。

我试过:

无论我做什么,在过程中的某个时刻都会出错。我知道这很简单,我做错了。有人能告诉我那可能是什么吗?

我非常强烈地认为 . 不应该只是在所有事情的中间,但我真的不知道。

同样,当我在 shell 参数字符串之前 运行 echo 时,一切看起来都应该如此。

如果需要我使用的更多脚本来理解我在说什么,那不是问题。

问题是因为你把它放在引号里 "${outputArgs}" 被扩展为一个参数。它不会被拆分成单独的参数,因此 ffmpeg 仅将其视为带有非常长的流说明符的单个 -c 选项。下一个参数,输出文件被解释为编解码器。

要解决此问题,只需删除引号:

"$command" $inputArgs "$input" $outputArgs "$directory$output$count.$extension"

我删除了花括号 ({}) 只是为了保存 space。如果您愿意,使用它们没有任何问题。

您试图依靠一个字符串来传达多个参数。您可能希望在所有此类情况下都使用数组。数组易于使用且用途更广(适用于任意字符串),您不必为了避免怪癖和安全漏洞而走那么多蛋壳,这与不使用引号不同。

command='ffmpeg'
inputArgs=(-i)
outputArgs=(-c:v libx264 -preset ultrafast -qp 0
  -metadata 'title=another * string'
  -metadata 'artist=; echo "Just a string'
  -metadata "comment=Processed by my ${command} script.")
directory="${HOME}/Desktop/Videos/"
output="video${count}"
extension='mp4'
outputArgs+=(-metadata "track=${count}")

展开数组时,引用周围必须有{}。当用于形式:"${name[@]}" 时,它的行为就像您直接在该行上键入内容一样。

echo 相比,

printf '%q\n' 是一种更有用的检查命令的方法,因为它可以清楚地告诉您什么属于哪个单独的参数。
您还可以展开一个数组转换成另一个数组:

whole_thing=("${command}" "${inputArgs[@]}" "${input}"
  "${outputArgs[@]}"
  "${directory}/${output}"."${extension}")

#This will output lines you can paste
# into bash to recreate the array:
printf 'whole_thing=()\n'
printf 'whole_thing+=(%q)\n' "${whole_thing[@]}"

#This will run the command:
"${whole_thing[@]}"