方便仓鼠党收集和去重,现将我写的格式化程序打包分享,此程序可以快速格式化指定目录下的文件夹格式(xP-xV-xMB),不用再一个个目录去统计了。
实现流程:golang遍历填入的目录,遍历目录下的目录,对目录里的文件进行计数统计,并重命名文件夹。
使用
格式化程序下载
92740e4c46161926.7z
7z文件
1.3M
已知问题
- 输入目录包含空格时,会直接退出程序 (已修复:2023-8-29 16:19:41)
源代码
package main
/**
* 目录名根据目录内文件数量进行格式化
*/
import (
"bufio"
"fmt"
mapset "github.com/deckarep/golang-set"
"io/ioutil"
"log"
"os"
"os/signal"
"path"
"path/filepath"
"regexp"
"strings"
)
var isdebug = false // false则重命名文件,否则只打印预览结果
var scanRootPath string // 搜索的要格式化的目录
// 是否删除除了 图片、视频、音频以外的文件
var isDelOtherFile = false
var photoExt = []interface{}{
".png",
".psd",
".jpg",
".jpe",
".jpg2",
".jpeg",
".gif",
".bmp",
".dif",
".wmf",
".svg",
".ico",
".tif",
".tiff",
".webp",
".heic",
".jfif",
}
var videoExt = []interface{}{
".mp4",
".mpg",
".mpe",
".mpeg",
".qt",
".mov",
".m4v",
".wmv",
".avi",
".webm",
".flv",
".mkv",
".ts",
}
var audioExt = []interface{}{
".mp3",
".mid",
".midi",
".wav",
".m3u",
".m4a",
".ogg",
".ra",
}
// 保存全部路径
var scanPathList []string
// 判断文件夹或文件是否存在
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
// 获取目录大小
func GetDirSize(path string) string {
var size int64
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
if !info.IsDir() {
size += info.Size()
}
return err
})
if err != nil {
panic("获取文件信息失败")
}
return ByteCountBinary(size)
}
// 字节转人类可读
func ByteCountBinary(b int64) string {
const unit = 1024
if b < unit {
return fmt.Sprintf("%dB", b)
}
div, exp := int64(unit), 0
for n := b / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.2f%cB", float64(b)/float64(div), "KMGTPE"[exp])
}
func ReplacePath(sourcePathname string) {
// 开始扫描此目录下的全部文件
sourcePathname = strings.ReplaceAll(sourcePathname, "\\", "/")
lastname := path.Base(sourcePathname)
photoNum := 0
videoNum := 0
audioNum := 0
err := filepath.Walk(sourcePathname, func(pathstr string, info os.FileInfo, err error) error {
if info.IsDir() == false {
ext := strings.ToLower(path.Ext(info.Name()))
switch {
case mapset.NewSetFromSlice(photoExt).Contains(ext):
photoNum += 1
case mapset.NewSetFromSlice(videoExt).Contains(ext):
videoNum += 1
case mapset.NewSetFromSlice(audioExt).Contains(ext):
audioNum += 1
default:
if isDelOtherFile && isdebug == false {
_ = os.Remove(pathstr)
fmt.Println("已删除其他类型文件", pathstr)
} else {
fmt.Println("找到其他类型文件", pathstr)
}
}
}
return err
})
if err != nil {
log.Println("扫描文件列表错误", err.Error())
return
}
var replacePath string
var dirinfoStr string
dirinfoStr = " ["
if photoNum > 0 || videoNum > 0 || audioNum > 0 {
if photoNum > 0 {
dirinfoStr += fmt.Sprintf("%dP", photoNum)
}
if videoNum > 0 {
fuhao := ""
if photoNum > 0 {
fuhao = "-"
}
dirinfoStr += fmt.Sprintf("%s%dV", fuhao, videoNum)
}
if audioNum > 0 {
fuhao := ""
if photoNum > 0 || videoNum > 0 {
fuhao = "-"
}
dirinfoStr += fmt.Sprintf("%s%dA", fuhao, audioNum)
}
}
fileSizeHuman := GetDirSize(sourcePathname)
var fuhao string
if photoNum > 0 || videoNum > 0 || audioNum > 0 {
fuhao = "-"
}
dirinfoStr += fmt.Sprintf("%s%s]", fuhao, fileSizeHuman)
// 匹配符号 "["
lastnameSplit := strings.Split(lastname, "[")
if len(lastnameSplit) > 0 {
for i := 0; i < len(lastnameSplit); i++ {
// 结尾必是数字开头
if regexp.MustCompile(`^\d+(P|V|A|B|MB|KB|GB|TB|PB|EB)`).MatchString(lastnameSplit[i]) {
lastname = strings.Replace(lastname, "["+lastnameSplit[i], "", 1)
}
}
}
replacePath = fmt.Sprintf("%s%s%s%s", path.Dir(sourcePathname), "/", strings.Trim(lastname, " "), dirinfoStr)
// 相同路径不操作
if strings.Contains(sourcePathname, dirinfoStr) && sourcePathname == replacePath {
log.Println("跳过已经重命名", sourcePathname)
return
}
// 判断重命名后的文件是否已存在
if PathExist, _ := PathExists(replacePath); PathExist == false {
// 不存在则进行重命名操作
log.Println("命名前:", sourcePathname)
log.Println("命名后:", replacePath, "\n")
if isdebug == false {
renameErr := os.Rename(sourcePathname, replacePath)
if renameErr != nil {
log.Println("Rename Error:", renameErr.Error())
}
}
} else {
// 名称在当前目录已存在,暂不操作
log.Println("替换后文件名冲突", sourcePathname, "替换后", replacePath)
}
}
func GetAllDirs(pathname string, s []string) ([]string, error) {
rd, err := ioutil.ReadDir(pathname)
if err != nil {
fmt.Println("read dir fail:", err)
return s, err
}
for _, fi := range rd {
if fi.IsDir() {
fullName := pathname + "\\" + fi.Name()
s = append(s, fullName)
}
}
return s, nil
}
func haveError() {
log.Println("结束:可 CTRL+C 或者 关闭窗口")
sigChan := make(chan os.Signal)
signal.Notify(sigChan)
<-sigChan
}
func main() {
fmt.Println("———— 格式化指定目录下目录名的程序 (CTRL+C可随时终止)")
fmt.Println("———— 注意:请勿直接输入盘符根目录,否则扫描路径下的全部目录都会格式化。")
fmt.Println("———— 根据以下后缀进行格式化")
fmt.Printf("图片:%v\n视频:%v\n音频:%v \n\n", photoExt, videoExt, audioExt)
fmt.Println("———— 是否调试模式(只打印结果) 请输入:[1:是 0:不是] 不填默认为0")
var inputIsDebug int
scanIsDebugN, _ := fmt.Scanln(&inputIsDebug)
if scanIsDebugN == 0 {
inputIsDebug = 0
}
if inputIsDebug == 0 {
isdebug = false
} else {
isdebug = true
}
fmt.Printf("调试模式:%v\n\n", isdebug)
if isdebug == false {
fmt.Println("———— 是否删除指定格式化后缀外的文件(谨慎选择) 请输入:[1:删除 0:不删除] 不填默认为0")
var inputIsDelOtherFile int
scaninputIsDelOtherFileN, _ := fmt.Scanln(&inputIsDelOtherFile)
if scaninputIsDelOtherFileN == 0 {
inputIsDelOtherFile = 0
}
if inputIsDelOtherFile == 0 {
isDelOtherFile = false
} else {
isDelOtherFile = true
}
fmt.Printf("删除其他文件:%v\n\n", isDelOtherFile)
}
fmt.Println("请粘贴要执行的目录地址(回车后执行):")
reader := bufio.NewReader(os.Stdin) // 标准输入输出
scanRootPath, _ = reader.ReadString('\n') // 回车结束
scanRootPath = strings.TrimSpace(scanRootPath)
scanRootPath = strings.Trim(scanRootPath, " ")
if scanRootPath == "" {
log.Println("错误:没有获取到你输入的目录")
haveError()
}
// 判断扫描的目录是否存在
if PathExist, _ := PathExists(scanRootPath); PathExist == false {
log.Printf("扫描的目录不存在 '%s'", scanRootPath)
return
}
//获取当前目录下的所有目录信息
var err error
scanPathList, err = GetAllDirs(scanRootPath, scanPathList)
if err != nil {
log.Println("读取当前目录出错", err.Error())
return
}
// 处理目录
for i, _ := range scanPathList {
loopPath := scanPathList[i]
ReplacePath(loopPath)
}
log.Println("运行结束,请检查格式化结果")
haveError()
}
温馨提示:本文最后更新于
注意:为了节省大家的时间,不会使用百度云下载也不愿意看解压说明教程、或者遇到不会解压的问题也不右下角私聊站长解决就直接投诉订单的朋友,还是别开通会员了,既浪费了您的时间也浪费了您的精力,感谢理解。→解压说明 2023-08-29 16:22:27
,某些文章具有时效性,若有错误或已失效,请在下方留言或者右下角私信。© 版权声明
THE END
请登录后查看评论内容