![为什么我的脚本无法正常运行?](https://linux22.com/image/153883/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E7%9A%84%E8%84%9A%E6%9C%AC%E6%97%A0%E6%B3%95%E6%AD%A3%E5%B8%B8%E8%BF%90%E8%A1%8C%EF%BC%9F.png)
我正在尝试./script.sh
像这样使用我的:
./compile.sh -n NAME_ALBUM -f 000 000 000 000 -l 000 000 000 000
- 在哪里-n是 ALBUM_NAME 并对应于正在保存的输出文件名
- 在哪里-F含义 First 是播放列表中首先出现的视频文件名列表
- 在哪里-l含义 Last 是播放列表中最后一个视频文件名的列表
然后播放列表被馈送到ffmpeg
...
#!/bin/sh
# usage: ./compile.sh -n NAME_ALBUM -f 000 000 000 000 -l 000 000 000 000
# OPTION -n is for NAME, video file NAME.
# OPTION -f is for FIRST, video numbers to come FIRST in playlist.
# OPTION -l is for LAST, video numbers to come LAST in playlist.
# NOTE: mp4 videos are numbered as 001.mp4, 002.mp4, 003.mp4
# NOTE: if no videoss are mentioned in -f or -l then it will be ignored by default.
# Q1: possible to use more than (4) videos in -f or -l ?
while getopts ":n:f:l:" options; do
case "${options}" in
n)
$1=${OPTARG}
;;
f)
$2=${OPTARG}
;;
l)
$3=${OPTARG}
;;
h)
echo "Help contents:
./compile.sh -n NAME_ALBUM -f 000 000 000 000 -l 000 000 000 000"
;;
:) # not sure what this is
echo "Error: -${OPTARG} requires an argument." #not sure what this is
exit_abnormal
;;
*) # or what this ones for
exit_abnormal
;;
esac
done
exit 0
# mp4 video file name that gets compiled
COMPILED=$1_$(date +'%Y-%m-%d_%H:%M:%S')
# video playlist fed to ffmpeg
VIDEO_LIST=list_$(date +'%Y-%m-%d_%H:%M:%S').txt
find *.mp4 | sed 's:\ :\\\ :g' | sed 's/^/file /' | sort -R > $VIDEO_LIST; (printf 'g?%s?m0\n' $2 ; printf 'wq\n') | ed -s $VIDEO_LIST; ( printf 'g?%s?m$\n' $3 | tac; echo 'wq'; ) | ed -s $VIDEO_LIST; ffmpeg -f concat -i $VIDEO_LIST -c:v libx264 -crf 12 -preset slow -c:a copy $COMPILED.mp4
到底是什么阻止了我的脚本工作?
问:这个脚本到底做了什么?
它为 ffmpeg 创建所需的播放列表,其中包含该目录中的视频(最好将视频重命名为 001.mp4、002.mp4 等,这使得附加的“第一个/最后一个”选项更易于使用)并随机随机播放所有视频播放列表中的视频并将其交给 ffmpeg 编译为一个视频。附加选项:如果需要使某些视频在播放列表中排在第一位或/和最后一位,只需输入数字即可。执行脚本时将文件名写入命令行。
答案1
除了 John1024 评论的内容之外,类似的参数-f file1 file2 file3
实际上会被读取为-f file1
:只有第一个值被读入脚本,其他值都会丢失。你的-l
论点也是如此。
您可以做的是指定一个字符串,它实际上是一个值列表(注意值周围的单引号):
./compile.sh -n NAME_ALBUM -f 'file1 file2 file3' -l 'file7 file8 file9'
这样,您将以:
- 您的选项的价值
-f
是“file1 file2 file3
” - 您的选项的价值
-l
是“file7 file8 file9
”
您“只需”拆分它们即可获取文件名。像这样的结构应该会启发你:
f='file1 file2 file3'; for fileName in $f; do echo "$fileName"; done
在评论中提出问题后编辑:
使用过程中需要报价吗?或者它们可以隐藏在脚本中吗?因为我已经想到了这一点,但我认为它们必须在脚本的命令行使用过程中使用,这不是我想要的。
这对我来说并不完全清楚,但我可以告诉你:
'file1 file2 file3'
(带引号)是单个字符串(带空格)并将其存储在变量中或将其作为参数传递(如-f <value>
)是完全可行的file1 file2 file3
(不带引号)是 3 个不同的字符串(因为空格充当参数分隔符。-f <value>
除非您使用像上面那样的 hack(即引号),否则您不能将 3 个值传递给构造中的单个参数
另外,$2 $3 $4 $5 as -f 和 $6 $7 $8 $9 as -l 怎么样?
混合getopts
构造和$n
参数最终会产生不可读的脚本。此外,该$n
策略涉及恰好有 4 个值-f
和 4 个值-l
。
我的建议仍然是为您的-f
和-l
选项提供文件列表:'file1 file2 file3'
并在脚本中剪切这些列表。
答案2
您可以用作|
一行中的最后一个字符,并且该行将继续。
例如
foo | bar | wc
相当于
foo |
bar |
wc
- 请注意,它将
;
像换行符一样分隔命令。
我缩进脚本的最后部分,在外部插入新行|
并;
最后一行看起来像
find *.mp4 |
sed 's:\ :\\\ :g' |
sed 's/^/file /' |
sort -R > $VIDEO_LIST
(printf 'g?%s?m0\n' $2 ; printf 'wq\n') |
ed -s $VIDEO_LIST
( printf 'g?%s?m$\n' $3 | tac; echo 'wq'; ) |
ed -s $VIDEO_LIST
ffmpeg -f concat -i $VIDEO_LIST -c:v libx264 -crf 12 -preset slow -c:a copy $COMPILED.mp4
? (其他答案解决了这一点)$2
来自哪里$3
?命令行 ?用于set alpha bravo charly
看起来像是
'\n'
第二个 sed 中缺少的内容。成为一名冒险家 将您的脚本提交给https://codereview.stackexchange.com/