go 文件操作

5 阅读2分钟

简介

很多时候会第一时间用linux命令进行文件操作,实际上直接用go的原生函数操作文件更加方便

需求

数据库表记录了需要保留的文件,里面可能是原始文件,也可能是链接文件,需要删除实际目录中其他的文件

  • 目录下有A B B1->B C C1->C D
  • 数据库有A B1
  • 需要删除C1 C D,保留文件A B B1

main.go

  • 根据数据库记录的文件名称,获取要保留的文件列表构建map,再遍历目录不在map中的进行删除即可
  • 保留文件判断
    • 如果是原始文件,保留文件也为原始文件
    • 如果是链接文件,保留文件为原始文件和链接文件
package main

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

// keepFileGet 保留文件列表获取
func keepFileGet(path string) []string {
	var keepFiles []string
	keepFiles = append(keepFiles, filepath.Base(path))
	fileInfo, err := os.Lstat(path)
	if err != nil {
		fmt.Println("err:", err)
	}
	if fileInfo.Mode()&os.ModeSymlink != 0 {
		// 获取软链接指向的目标
		target, err := os.Readlink(path)
		if err != nil {
			fmt.Println("err:", err)
		}
		keepFiles = append(keepFiles, filepath.Base(target))
	}
	return keepFiles
}

func main() {
	// 指定要处理的目录
	dirPath := "./imgs/"

	// 初始化
	os.Create(dirPath + "A")
	os.Create(dirPath + "B")
	os.Create(dirPath + "C")
	os.Create(dirPath + "D")
	os.Symlink("B", dirPath+"B1")
	os.Symlink("C", dirPath+"C1")

	// 获取数据库中的文件列表
	dbFiles := []string{"A", "B1"}

	// 获取完整保留文件列表
	var keepFiles = make(map[string]bool)
	for _, ob := range dbFiles {
		kObs := keepFileGet(dirPath + ob)
		for _, kob := range kObs {
			keepFiles[kob] = true
		}
	}
	fmt.Println("keepFiles:", keepFiles)

	// 遍历目录
	filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		// 跳过目录
		if info.IsDir() {
			return nil
		}
		_, ok := keepFiles[filepath.Base(path)]
		if !ok {
			os.Remove(path)
			fmt.Println("remove:", path)
		}

		return nil
	})
}

运行

[xiaofeng@localhost fileopr]$ go run main.go 
keepFiles: map[A:true B:true B1:true]
remove: imgs/C
remove: imgs/C1
remove: imgs/D
[xiaofeng@localhost fileopr]$ 
[xiaofeng@localhost fileopr]$ ls -l imgs/
total 0
-rw-rw-r-- 1 xiaofeng xiaofeng 0 Jan  8 15:18 A
-rw-rw-r-- 1 xiaofeng xiaofeng 0 Jan  8 15:18 B
lrwxrwxrwx 1 xiaofeng xiaofeng 1 Jan  8 14:52 B1 -> B

总结

  • os.Create 创建文件
  • os.Remove 删除文件
  • os.Lstat 获取文件信息
    • fileInfo.Mode()&os.ModeSymlink != 0 判断是否为链接文件
    • fileInfo.IsDir() 判断是否为目录
  • filepath.Base() 返回最后元素,如/a/b/c.tar返回c.tar
  • filepath.Walk 遍历目录