我有几个不同分辨率的视频文件。现在我想仅列出分辨率为 720p 的视频文件名。我更喜欢在 bash 命令行上使用一行代码,这样当我执行以下命令时,我可以收到有用的视频信息,包括分辨率:
avconv -i video.mp4
但这种组合:
find -exec sh -c 'if [[ "$(avconv -i {}") == *720* ]] ; then echo 720 found; fi;'
产生错误:exec-缺少参数。
说实话,我很少与 bash 命令结构发生冲突,尤其是组合命令。那么,我的组合命令字符串有什么问题?
谢谢。
答案1
也许这个命令可以完成您所寻找的任务:
for i in *.mp4; do if [[ $(avconv -i $i) =~ .*720.* ]]; then echo $i; fi; done
答案2
这可能令人惊讶但-exec
可以用作find
调用中的测试:
find -type f -exec sh -c 'ffprobe -show_streams 2>/dev/null "$1" | grep -q coded_height=720' sh {} \; -print
上述命令将进入子目录。要在当前目录中搜索,只需使用-maxdepth 1
,即:
find -maxdepth 1 -type f -exec …
请注意,将测试所有文件。对于非媒体文件,它显然会失败,但您可能会在最终输出中ffprobe
获得非视频媒体(如)。为避免这种情况,应在之前使用一些额外的测试,例如:.jpg
find
-exec
find -maxdepth 1 -type f \( -iname "*.avi" -o -iname "*.mp4" -o -iname "*.mkv" \) -exec sh -c 'ffprobe -show_streams 2>/dev/null "$1" | grep -q coded_height=720' sh {} \; -print
或者更好的是,你可以使用以下方法测试 mime 类型file
:
find -maxdepth 1 -exec sh -c 'file --mime-type "$1" | grep -q "video/"' sh {} \; -exec sh -c 'ffprobe -show_streams 2>/dev/null "$1" | grep -q coded_height=720' sh {} \; -print
阅读man find
以了解更多信息。
编辑:
该命令(误)使用了avconv
,正如您所要求的:
find -exec sh -c 'file --mime-type "$1" | grep -q "video/"' sh {} \; -exec sh -c 'avconv 2>&1 -i "$1" | grep -q "Stream.*x720"' sh {} \; -print
问题是每次调用avconv
都会抛出错误。我们只是忽略它并提取我们需要的信息。这是一个有点丑陋的解决方案。我不完全确定你的avconv
行为是否和我的一样,你可能需要Stream.*x720
用其他正则表达式替换。
我的组合命令字符串有什么错误?
find -exec
需要用\;
或结束+
,在您编辑问题后,有无$(
)
交错(""
不嵌套)$()
,*720*
可能会触发 shell 通配符,应该是"*720*"
(我说的是sh
,而不是外壳),avconv
您尝试解析的输出为stderr
,我认为您需要先重定向它,然后才能解析它,- 或许还有其他东西。
答案3
我不知道 avconv,我通常使用 ffmpeg。如果你安装了它,你可以使用这个脚本
#!/bin/bash
OIFS="$IFS"
IFS=$'\n'
files=$(find ./ -type f -exec ls {} + | grep ".*\.mpg$\|.*\.avi$\|.*\.mkv$\|.*\.mp4$"| cut -c3-)
for f in ${files}
do
resolution=$(ffprobe -v error -select_streams v:0 -show_entries
stream=height -of csv=s=x:p=0 ${f})
printf "%-100s %-10s\n" $f $resolution
done
答案4
目前我找到了一个可用的解决方案:
for i in ls *.m??; do sm=$(mediainfo $i | grep Height | sed 's/ //g');if [[ "$sm" == *720* ]]; then printf "Video: %-s $i %-s $sm \n"; fi; done
在这里我可以循环播放所有 m?? 视频文件并打印其名称(包括“720”条件)。如果没有 if 部分,我可以显示所有视频及其分辨率。
我在当地其他答案的帮助下解决了这个问题。
当我尝试将 find 和 exec 以及上述解决方案的 do 部分结合起来时,我只收到来自每个主题的 mediainfo 的“E:文件读取错误”消息:
find -exec mediainfo "{}" \; -exec bash -c 'sm=$(mediainfo ${} | grep 720) : ; echo $sm' \;
正如我所说,“if”构造有效(对于实际目录),但我也会尝试让它与 find 一起运行。