使用go编写的文件树遍历(递归遍历所有文件夹和文件)

415 阅读1分钟

文件树遍历

引子

某位同事小哥哥找到我,说领导让他把收集到全国各地的文章整理一下,有的地区的文章在别的地区里,比较急,让我帮忙想想办法,我立马去百度找了个windows文件树查看,他说要复制到表格里,默认的不行,让我给他写一个,想了想go可以直接生成不同端的不同文件,不用额外安装运行环境,开搞开搞

用到的库

flag 命令行工具,解析参数; bufio 通过缓存来提高效率,缓存放在主存中; os 包之目录和文件(file)的操作; 功能 可以通过命令行指定输出文件还是文件夹树,并且输出到txt,便于复制

代码

主入口

func main() {
   var folder bool
   var document bool
   var rootPath string

   flag.BoolVar(&folder, "r", true, "文件夹")
   flag.BoolVar(&document, "d", false, "文件")
   flag.StringVar(&rootPath, "rp", "", "要遍历的根文件夹")
   flag.Parse()
   if rootPath == "" {
      exPath, _ := os.Getwd()
      rootPath = exPath
   }

   filePath := "out.txt"
   var err = os.Remove(filePath)
   _, err1 := os.Create(filePath)
   if err != nil {
      return
   }
   if err != nil && err1 != nil {
      return
   }

   file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_APPEND, 0666)

   if err != nil {
      fmt.Println("文件打开失败", err)
   }
   // 及时关闭file句柄
   defer func(file *os.File) {
      err = file.Close()
   }(file)
   write := bufio.NewWriter(file)
   getPath(folder, document, rootPath, "", write)

}

文件树逻辑


func getPath(folder bool, document bool, rootPath string, indent string, write *bufio.Writer) {
	files, err := ioutil.ReadDir(rootPath)
	if err != nil {
		fmt.Println("read file path error", err)
		return
	}
	for i := 0; i < len(files); i++ {
		if files[i].Name()[0] == '.' {
			files = append(files[:i], files[i+1:]...)
		}
	}
	dirs := make([]string, 0)

	if document {
		for _, fi := range files {
			if !fi.IsDir() {
				dirs = append(dirs, fi.Name())
			}
		}
	}

	lenFile := len(dirs)
	if folder {
		for _, fi := range files {
			if fi.IsDir() {
				dirs = append(dirs, fi.Name())
			}
		}
	}

	// 最后一个文件的分支用
	for i := 0; i < len(dirs); i++ {
		if i == len(dirs)-1 {
			fmt.Println(indent + "└── " + dirs[i])
			_, err := write.WriteString(indent + "└── " + dirs[i] + "\r\n")
			if err != nil {
				return
			}
			e := write.Flush()
			if e != nil {
				return
			}
			if i >= lenFile {
				getPath(folder, document, rootPath+"/"+dirs[i], indent+"   ", write)
			}
		} else {
			fmt.Println(indent + "├── " + dirs[i])
			_, err := write.WriteString(indent + "├── " + dirs[i] + "\r\n")
			if err != nil {
				return
			}
			e := write.Flush()
			if e != nil {
				return
			}
			if i >= lenFile {
				getPath(folder, document, rootPath+"/"+dirs[i], indent+"│  ", write)
			}
		}

	}
}

使用

go run main.go file_name.go

参数

-r 指定显示文件夹 -d 指定显示文件 -rp 指定要便利的文件夹 (默认当前路径)

源码路径