按时长查找所有视频文件

按时长查找所有视频文件

我想将所有具有一定时长的视频文件移动到某个目录。在这个答案我找到了一种探测视频文件时长的方法:

ffprobe-i一些视频-show_entries 格式=持续时间-v 安静-of csv="p=0"

我想用它做这样的事:

find . -test <test for duration> -exec mv {} /path/to/target ';'

但是,似乎find不支持测试的任意脚本(没有-test开关)。我错过了什么吗?这根本就不可能吗find?我最好只写一个python脚本吗?

答案1

你可以使用-exec-test编写一个脚本,接受一个文件名参数,如果文件符合条件则退出 0,否则退出非零。我的系统上没有 FF 软件(例如 ffprobe),所以我无法检查这一点,但类似

#!/bin/sh
if dur=$(ffprobe -i "$1" -show_entries format=duration -v quiet -of csv="p=0")
then
        [ "$dur" -ge 900 ]
        exit
else
        exit
fi

将检查视频的持续时间是否大于等于 15 分钟,假设ffprobe输出为整数秒数。(如果它报告 mm:ss 或 ss.ddd,我将一些琐碎的修改留给您,但请参见下面的示例以获得启发。)解释:if如果失败,则ffprobe失败;在这种情况下,我们将下降到较低的位置exit 并以错误状态从 退出ffprobe。如果ffprobe成功,我们测试其输出("$dur"),然后使用该测试的结果退出。这也可以写成

[ "$dur" -ge 900 ]  &&  exit 0  ||  exit 1

事实上,全部的脚本实际上可以简化为

dur=$(ffprobe -i "$1" -show_entries format=duration -v quiet -of csv="p=0")  \
                            &&  [ "$dur" -ge 900 ]

因此,将脚本命名为check_dur

find . -exec ./check_dur {} ';'-exec mv {} /path/to/target ';'

这是有效的,因为正如我所说,-exec它起到测试的作用,-exec只有第一次-exec成功(以状态 0 退出)后的事情才会被处理。

正如我所说的,我的系统上没有 FF 软件(例如ffprobe),因此我使用这个脚本进行了测试:

#!/bin/sh
if mod=$(stat -c%y "$1")
then
        mod=${mod#*-}
        mod=${mod%%-*}
        mod=${mod#0}
        [ $(( mod%2 )) = 0 ]
        exit
else
        exit
fi

测试文件或目录的修改日期是否在双数月。注意:在我的 (en_US) 系统上, 以 格式输出修改日期。因此,上述代码stat -c%y filenameyyyy-mm-dd HH:MM:SS.ddddddddd -(TZ)

  1. 去掉年份(从左边开始),
  2. 去掉月份后面的所有内容,然后
  3. 去掉前导的0(如果有)(因为$((…))将前导零解释为数字是八进制的指示,因此它会报告08和 的错误09)。

其他几点说明:

  1. 对于mv,可以通过将命令更改为来稍微改进一下

     find . -exec ./check_dur {} ';' -exec mv -t /path/to/target {} +
    

它将mv对许多文件执行一次。您不能对第一个执行此操作-exec,因为-exec ... +不能用作测试。2. 如果您不想编写单独的脚本,则可以使用sh -c并内联脚本;例如,

    find . -exec sh -c 'dur=$(ffprobe -i "$1" -show_entries format=duration -v quiet -of csv="p=0") && [ "$dur" -ge 900 ]' sh {} ';'-exec mv -t /path/to/target {} +

这将创建一个单行小脚本( 后面的字符串sh -c),并将文件名 ( {}) 作为参数传递给它。 的某些版本find 允许您将 合并{}到小脚本中,但这不是一个好主意:

  • 它不适用于所有版本的find,并且
  • 即使它有效,一般来说,对于某些文件名它也会失败(甚至可能灾难性地失败)。

相关内容