Commond line tool

需求描述

我电脑的一个文件夹里有成百上千的文件,我想找一个最小的视频文件(用 ffmpeg 来玩, 先每隔几秒抽帧再把抽的帧合成一个视频)。

需求分析

此文旨在解决前一个需求,即:在一个文件夹中查找一个最小的视频文件。用 Golang 写一个命令行小工具来查找(旨在练手和记录📝)。

后一个需求(ffmpeg 抽帧再合成帧)见稍后的文档。

前提条件

工程实现

1. 创建项目文件夹

打开命令行执行:

mkdir -p minvideo && cd minvideo 

2. 初始化项目

go mod init minvideo

3. 创建代码文件

touch main.go

4. 编辑代码文件

需事先安装好 visual studio code 命令行工具。

code .

代码:

package main

import (
    "flag"
    "fmt"
    "os"
    "path/filepath"
    "strings"
)

func main() {
    // 定义参数
    recursive := flag.Bool("r", false, "是否递归扫描子目录")
    flag.Parse()

    if flag.NArg() < 1 {
        fmt.Println("用法: minvideo [-r] <目录路径>")
        return
    }
    root := flag.Arg(0)

    videoExts := []string{".mp4", ".mov", ".mkv", ".avi", ".flv", ".wmv"}
    var minFile string
    var minSize int64 = -1

    err := filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error {
        if err != nil {
            return err
        }

        // 跳过根目录本身
        if path == root {
            return nil
        }

        // 如果不是递归模式,遇到目录就跳过
        if d.IsDir() && !*recursive {
            return filepath.SkipDir
        }

        // 检查扩展名是否为视频
        ext := strings.ToLower(filepath.Ext(d.Name()))
        if !contains(videoExts, ext) {
            return nil
        }

        info, err := d.Info()
        if err != nil {
            return nil
        }

        size := info.Size()
        if minSize == -1 || size < minSize {
            minSize = size
            minFile = path
        }

        return nil
    })

    if err != nil {
        fmt.Println("遍历目录时出错:", err)
        return
    }

    if minFile == "" {
        fmt.Println("目录中没有找到视频文件")
    } else {
        fmt.Printf("最小的视频文件: %s (%.2f MB)\n", minFile, float64(minSize)/1024/1024)
    }
}

func contains(list []string, target string) bool {
    for _, v := range list {
        if v == target {
            return true
        }
    }
    return false
}

5. 编译

go build -o minvideo main.go

6. 放到 PATH 里

如果你想在任何目录下都能运行,可以把它放到 /usr/local/bin

sudo mv minvideo /usr/local/bin/

7. 清理

cd .. && rm -rf minvideo

使用示例

  • 只扫描一层目录
minvideo ~/Downloads/videos
  • 递归扫描所有子目录
minvideo -r ~/Downloads/videos