feat(core): 实现扫描并删除iPhone导出相册中的实况视频功能

- 新增文件扫描逻辑,遍历目录下所有文件并记录路径与元信息
- 新增核心处理逻辑,识别.HEIC图片及其对应的.MOV实况视频
- 自动将匹配的实况视频移动至 duplicates 目录以供用户确认删除
- 添加构建脚本build.sh用于编译和压缩可执行文件
- 更新.gitignore忽略.idea目录
- 重写README.md,明确工具用途、需求及效果预览
- 初始化模块依赖管理(go.mod, go.sum)及相关工具类和变量定义
This commit is contained in:
2025-12-20 10:01:08 +08:00
parent e7374097bc
commit 1364404123
14 changed files with 1260 additions and 69 deletions
+41
View File
@@ -0,0 +1,41 @@
package core
import (
"fmt"
"kenaito-media-group-tool/util"
"kenaito-media-group-tool/vars"
"log"
"os"
"path"
"path/filepath"
)
type FileScanner struct {
}
func (FileScanner) DoScan(rootDir string) {
fmt.Printf("=== 开始扫描文件 \n")
if err := filepath.Walk(rootDir, visitFile); err != nil {
log.Fatal(err)
}
}
// 定义walkFn回调函数visit
func visitFile(currentPath string, info os.FileInfo, err error) error {
if err != nil {
return err // 如果有错误,直接返回
}
if !info.IsDir() {
ext := path.Ext(currentPath)
if ".exe" != ext {
vars.GlobalFilePathList = append(vars.GlobalFilePathList, currentPath)
// filename, include ext
vars.GlobalFilePath2FileNameExtMap[currentPath] = filepath.Base(currentPath)
// filename, exclude ext
vars.GlobalFilePath2FileNameMap[currentPath] = util.GetFileNameWithoutExt(currentPath)
// file ext
vars.GlobalFilePath2FileExtMap[currentPath] = ext
}
}
return nil
}
+74
View File
@@ -0,0 +1,74 @@
package core
import (
"fmt"
"github.com/redmask-hb/GoSimplePrint/goPrint"
uuid "github.com/satori/go.uuid"
"kenaito-media-group-tool/util"
"kenaito-media-group-tool/vars"
"os"
"strings"
)
func DoDeleteLiveVideo(rootDir string) {
pathSep := string(os.PathSeparator)
uid := strings.ReplaceAll(uuid.NewV4().String(), "-", "")
total := len(vars.GlobalFilePathList)
fmt.Printf("=== 文件总数: %d \n", total)
for _, filePath := range vars.GlobalFilePathList {
fileExt := vars.GlobalFilePath2FileExtMap[filePath]
if ".HEIC" == fileExt {
vars.GlobalHEICFilePathNameMap[filePath] = vars.GlobalFilePath2FileNameMap[filePath]
continue
}
if ".MOV" == fileExt {
vars.GlobalMOVFilePathPathNameMap[filePath] = vars.GlobalFilePath2FileNameMap[filePath]
}
}
var movFilePath []string
for _, heicName := range vars.GlobalHEICFilePathNameMap {
for movPath, movName := range vars.GlobalMOVFilePathPathNameMap {
if heicName == movName {
println(movPath)
movFilePath = append(movFilePath, movPath)
}
}
}
fmt.Printf("=== 发现实况视频文件数量: %d\n", len(movFilePath))
duplicatesDir := rootDir + pathSep + "duplicates-" + uid
util.CreateDir(duplicatesDir)
fmt.Printf("=== 开始移动实况视频文件")
doMoveFileToDir(movFilePath, duplicatesDir)
fmt.Printf("=== 实况视频已移动到: %v 中\n", duplicatesDir)
}
// 批量移动文件到目录
func doMoveFileToDir(filePathList []string, videoDirPath string) {
total := len(filePathList)
var count = 0
bar := goPrint.NewBar(100)
bar.SetNotice("=== 移动文件到目录:")
bar.SetGraph(">")
pathSeparator := string(os.PathSeparator)
for _, videoFilePath := range filePathList {
moveFileToDir(videoFilePath, videoDirPath+pathSeparator)
count = count + 1
bar.PrintBar(util.CalcPercentage(count, total))
}
bar.PrintEnd("=== Finish")
}
// 移动文件到目录
func moveFileToDir(sourceFilePath string, targetDirectory string) bool {
splits := strings.Split(sourceFilePath, string(os.PathSeparator))
fileName := splits[len(splits)-1]
targetFilePath := targetDirectory + fileName
err := os.Rename(sourceFilePath, targetFilePath)
//fmt.Printf("=== 移动文件, 源: %s, 目标: %s \n", sourceFilePath, targetFilePath)
return err == nil
}