如何按时长筛选并移动视频文件?find工具能否支持自定义脚本检测?
哈哈,其实你并没有漏掉find的核心功能——它确实没有专门的-test选项来直接调用自定义检测脚本,但我们可以用-exec选项来实现完全相同的效果!不用急着直接写Python脚本,先看看find怎么配合自定义逻辑完成这个需求。
find的-exec就是用来让你调用任意外部命令或脚本的,只要你的检测逻辑在判断符合条件时返回0(shell中的“成功”状态),就可以配合find筛选文件并执行后续操作。
最实用的方案是结合ffprobe(ffmpeg套件里的工具,专门提取媒体元数据)来检测视频时长,下面是两种具体实现方式:
方法1:Inline Shell 命令(无需单独写脚本)
直接在find命令里嵌入一段shell逻辑,不用额外创建脚本文件:
# 替换成你的实际路径和时长条件 SOURCE_DIR="/path/to/your/videos" TARGET_DIR="/path/to/target/directory" # 示例:筛选时长≥3600秒(1小时)的视频 MIN_DURATION=3600 find "$SOURCE_DIR" -type f \( -name "*.mp4" -o -name "*.mkv" -o -name "*.avi" \) -exec sh -c ' for file do # 用ffprobe获取视频时长(单位:秒,取整数部分) duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file" | cut -d. -f1) # 判断时长是否符合条件,符合就移动 if [ "$duration" -ge '$MIN_DURATION' ]; then mv "$file" '"$TARGET_DIR"'/ echo "Moved: $file" fi done ' sh {} +
这段命令的关键细节:
-type f只查找文件,排除目录\( -name "*.mp4" ... \)匹配常见视频格式,你可以按需添加更多后缀-exec sh -c '...' sh {} +批量传递找到的文件给shell处理,{} +比{} \;效率更高,因为会一次性传递多个文件
方法2:单独写检测脚本
如果逻辑更复杂,你可以写一个独立的shell脚本(比如check_duration.sh),再用find调用它:
#!/bin/bash # check_duration.sh FILE="$1" MIN_DURATION=3600 duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$FILE" | cut -d. -f1) if [ "$duration" -ge "$MIN_DURATION" ]; then exit 0 # 返回0表示符合条件 else exit 1 # 返回非0表示不符合 fi
给脚本加执行权限:chmod +x check_duration.sh,然后用find调用:
find "$SOURCE_DIR" -type f -name "*.mp4" -exec ./check_duration.sh {} \; -exec mv {} "$TARGET_DIR" \;
这里-exec ./check_duration.sh {} \;会筛选出返回0的文件,后面的-exec mv ...只会处理这些符合条件的文件。
如果你的需求比较复杂,比如:
- 需要同时处理多种时长条件(比如把10-20分钟、30分钟以上的视频分到不同目录)
- 需要处理特殊格式视频,或者完善的错误处理(比如ffprobe提取时长失败的情况)
- 你本身更熟悉Python,想要更易读、易维护的代码
那写Python脚本确实是更好的选择。比如用ffprobe-python库来提取时长:
import os import shutil from ffprobe import FFProbe # 配置参数 source_dir = "/path/to/your/videos" target_dir = "/path/to/target/directory" min_duration = 3600 # 单位:秒 # 确保目标目录存在 os.makedirs(target_dir, exist_ok=True) # 遍历所有视频文件 for root, _, files in os.walk(source_dir): for file in files: if file.lower().endswith((".mp4", ".mkv", ".avi", ".mov")): file_path = os.path.join(root, file) try: # 提取视频元数据 media = FFProbe(file_path) # 获取时长(转换为秒) duration = float(media.streams[0].duration) # 判断并移动,同时处理重名文件 if duration >= min_duration: target_path = os.path.join(target_dir, file) if os.path.exists(target_path): target_path = os.path.join(target_dir, f"{os.path.splitext(file)[0]}_copy{os.path.splitext(file)[1]}") shutil.move(file_path, target_path) print(f"Successfully moved: {file_path} -> {target_path}") except Exception as e: print(f"Failed to process {file_path}: {str(e)}")
这个脚本的优势在于可以轻松扩展逻辑,比如添加日志记录、支持更多格式、自定义重名处理规则等。
总结一下:你并没有遗漏find的功能,用-exec就能结合自定义检测逻辑完成需求;如果需求简单,find+shell足够高效;如果逻辑复杂,Python脚本会更灵活。
内容的提问来源于stack exchange,提问作者user1785730

