前一段时间,我问我尝试执行的bash脚本出了什么问题,我得到了一个很好的解决方案:What's wrong with this youtube-dl automatic script?
我一直在修改脚本以使其与不同的youtube-dl命令组合一起使用,并处理我的非常不稳定互联网连接(这是while / do循环的原因),并且该脚本可以正常工作,但是,当我尝试使用相同的脚本结构从列表中的特定项目(例如,项目编号15)开始下载Youtube播放列表时,这就是我遇到错误的时间。我仍然是bash脚本的新手(显然),所以我不知道出了什么问题。
有问题的脚本是这样的:
#!/bin/bash
function video {
youtube-dl --no-warnings -o '%(playlist)s/%(playlist_index)s - %(title)s.%(ext)s' --socket-timeout 15 --hls-use-mpegts -R 64 --fragment-retries 64 --prefer-free-formats --all-subs --embed-subs -f 'bestvideo[height<=720]+bestaudio/best[height<=720]' "$@"
}
read -p "url: " url
video "$url"
while [ $? -ne 0 ]; do sleep 5 && video "$url" ; done
clear && echo completed!
因此,例如,如果我尝试下载播放列表,则只需在终端上写:
printf https://www.youtube.com/playlist?list=PLS1QulWo1RIYmaxcEqw5JhK3b-6rgdWO_ | list720
(““ list720”当然是脚本的名称)该脚本运行没有问题,并且完全符合我的期望。
但是,如果我在终端机中运行:
printf --playlist-start=15 https://www.youtube.com/playlist?list=PLS1QulWo1RIYmaxcEqw5JhK3b-6rgdWO_ | list720
我收到以下错误消息:
bash: printf: --: invalid option
printf: usage: printf [-v var] format [arguments]
ERROR: '' is not a valid URL. Set --default-search "ytsearch" (or run youtube-dl "ytsearch:" ) to search YouTube
如果我颠倒顺序(首先是youtube URL,然后是--playlist-start = 15命令),则脚本会下载整个播放列表,并忽略“ --playlist-start”命令。
我尝试直接在终端中直接运行youtube-dl命令字符串,并在末尾添加了“ --playlist-start”和URL,它可以完美运行:
youtube-dl --no-warnings -o '%(playlist)s/%(playlist_index)s - %(title)s.%(ext)s' --socket-timeout 15 --hls-use-mpegts -R 64 --fragment-retries 64 --prefer-free-formats --all-subs --embed-subs -f 'bestvideo[height<=720]+bestaudio/best[height<=720]' --playlist-start=15 https://www.youtube.com/playlist?list=PLS1QulWo1RIYmaxcEqw5JhK3b-6rgdWO_
...所以我认为问题出在脚本上。
欢迎任何帮助,谢谢!
答案 0 :(得分:1)
更好的设计是接受任何选项和URL作为命令行参数。需要交互式I / O的脚本讨厌包含在较大的脚本中,并且通常较难使用(您失去了使用Shell的制表符补全和命令行历史记录等功能的能力。)
#!/bin/bash
# Don't needlessly use Bash-only syntax for declaring a function
# Indent the code
video () {
youtube-dl --no-warnings \
-o '%(playlist)s/%(playlist_index)s - %(title)s.%(ext)s' \
--socket-timeout 15 --hls-use-mpegts -R 64 --fragment-retries 64 \
--prefer-free-formats --all-subs --embed-subs \
-f 'bestvideo[height<=720]+bestaudio/best[height<=720]' "$@"
}
until video "$@"; do
sleep 5
done
完成后清除屏幕似乎是敌对的,所以我也把它拿出来了。
现在,如果您要将其他参数传递给youtube-dl
,只需将它们作为脚本的参数包括在内即可。
list720 --playlist-start=15 'https://www.youtube.com/playlist?list=PLS1QulWo1RIYmaxcEqw5JhK3b-6rgdWO_'
如果URL中包含shell元字符,则通常还应引用它们。另请参见When to wrap quotes around a shell variable?
请注意,我们始终如何{em> 注意在"$@"
周围使用双引号;在这种情况下忽略它们只是一个错误。
还请注意"$@"
在函数内部是如何引用函数的参数的,而在主脚本中,它是如何引用脚本的命令行参数的。
也可能不使用格式字符串而使用printf
也是有问题的。如果您传递的字符串中包含一个百分号字符,则那个将被解释为格式字符串。
bash$ printf 'http://example.com/%7Efnord'
http://example.com/0.000000E+00fnord
正确的解决方案是始终将格式字符串作为第一个参数。
bash$ printf '%s\n' 'http://example.com/%7Efnord'
http://example.com/%7Efnord
但是您不需要printf
来传递某些内容作为标准输入。 Bash有“这里的字符串”:
list720 <<<'http://example.com/%7Efnord'
(这当然只适用于从标准输入中读取URL的旧版本;此答案中的重构脚本无法正常工作。)
答案 1 :(得分:0)
我的兄弟(一位“退休”的程序员)花了一些时间评估Bash脚本的工作方式,我们找到了一种方法,只需添加youtube-dl命令和Youtube URL作为参数,便可以使脚本更简单地工作。
脚本稍作更改,现在看起来像这样:
indexPath.row
现在我只需要在终端上写:
#!/bin/bash
function video() {
youtube-dl --no-warnings -o '%(playlist)s/%(playlist_index)s - %(title)s.%(ext)s' --socket-timeout 15 --hls-use-mpegts -R 64 --fragment-retries 64 --prefer-free-formats --all-subs --embed-subs -f 'bestvideo[height<=720]+bestaudio/best[height<=720]' "$@"
}
video $@
while [ $? -ne 0 ]; do sleep 5 && video $@ ; done
clear && echo completed!
它完全按照我的意愿来工作。
答案 2 :(得分:-2)
在bash中,命令开头的字符“-”用于设置选项,如果要打印--playlist...
,则应使用转义字符“ \”。
尝试类似 printf "\-\-playlist..."
更正:printf'%s''-播放列表...'