golang批量整理markdown文件的图片存放路径【支持多级目录】

按照.${filename}.assets的格式批量整理markdown文件的图片存放路径

由于我的笔记和图都在一个根目录下,且之前的图片存放路径都是在本层级的相对路径,适用于绝对路径和本层级及以下的相对路径;图片只考虑了jpg和png两种情况,有其他需求可以修改strings.HasPrefix这部分代码

// ChangeDir 移动照片(文件都存放在md笔记同目录下) 传入的rootPath格式参照	"D:/AStudy/typora"
func ChangeDir(rootPath string) {
	files, err := ioutil.ReadDir(rootPath)
	if err != nil {
		fmt.Printf("读取目录【%v】失败,错误:%+v\n", rootPath, err)
		return
	}

	//正则匹配文件链接
	//<img src=".02-1wagger给前端看的文档.assets\image-2013405.png" alt="image-2065013405" style="zoom:70%;" />
	//![算法名称是否唯一](.02-2Q&R.assets\算法名称是否唯一.png)
	reg := regexp.MustCompile(`(\<img src=\"|\]\(){1,1}([^\^)"]*)`)

	//遍历文件
	for _, file := range files {
		filename := file.Name()
		//是目录
		if file.IsDir() {
			//递归接着读
			ChangeDir(rootPath + "/" + filename)
		} else { //是文件
			//判断是否为md文件
			ext := filepath.Ext(filename)
			if ext == ".md" {
				filePath := rootPath + "/" + filename
				buf, err := ioutil.ReadFile(filePath)
				if err != nil {
					fmt.Printf("读取文件【%v】失败,错误:%+v\n", filePath, err)
					return
				}
				// 每次更新链接的暂存数据
				tmpMdStr := string(buf)
				// 匹配图片格式正则
				matches := reg.FindAllStringSubmatch(tmpMdStr, -1)
				//遍历每一个图片,判断图片是否存在
				for _, match := range matches {
					//获取全部路径
					mdImgPath := match[2]
					//是本地图片(以.jpg/.png结尾,不是http开头
					if !strings.HasPrefix(mdImgPath, "http") && (strings.HasSuffix(mdImgPath, ".png") || strings.HasSuffix(mdImgPath, ".jpg")) {
						//不是绝对路径
						if !filepath.IsAbs(mdImgPath) {
							//添加前缀,改为绝对路径
							mdImgPath = rootPath + "/" + mdImgPath
						}
						//是否存在该文件
						flag, sourcePath := fileExists(mdImgPath)
						if flag {
							//md文件名(无后缀)
							fileStr := filename[:len(filename)-len(ext)]
							//应存放的文件夹名称
							toPath := "." + fileStr + ".assets"
							//应存放的文件夹的绝对路径
							fullDir := rootPath + "/" + toPath
							//md文件里图片的相对路径
							toMatch := toPath + "/" + filepath.Base(sourcePath)
							//图片的绝对路径
							destPath := rootPath + "/" + toMatch
							//判断目的文件夹是否存在,不存在就创建
							err = checkDir(fullDir)
							if err != nil {
								fmt.Printf("创建文件夹【%v】失败,错误:%+v\n", toPath, err)
								return
							}
							//如果目的地址不一样,则移动文件并更新链接
							if sourcePath != destPath {
								//移动文件
								err := os.Rename(sourcePath, destPath)
								if err != nil {
									fmt.Printf("移动文件【%v】到【%v】失败,错误:%+v\n", sourcePath, destPath, err)
								} else {
									//更新md文档链接
									tmpMdStr = strings.Replace(tmpMdStr, match[2], toMatch, 1)
									//重新写入
									err := ioutil.WriteFile(filePath, []byte(tmpMdStr), 0)
									if err != nil {
										fmt.Printf("md更新链接失败:【%v】到【%v】,错误:%+v\n", sourcePath, destPath, err)
										//试图恢复图片,如果再失败则无法挽回
										err := os.Rename(destPath, sourcePath)
										if err != nil {
											fmt.Printf("【回滚失败,图片已移动但文档未更新,请尝试失败的操作恢复文档可读性】试图恢复:移动文件【%v】到【%v】失败,错误:%+v\n", destPath, sourcePath, err)
										}
									}
								}
							}
						} else {
							fmt.Printf("%v下文件%v不存在\n", rootPath+"/"+filename, sourcePath)
						}
					}
				}
			}
		}
	}
}

// fileExists 文件是否存在
func fileExists(filePath string) (bool, string) {
	_, err := os.Stat(filePath)
	flag := err == nil || os.IsExist(err)
	//如果不存在
	if !flag {
		//%还原为中文再判断一次
		sourcePath2, _ := url.QueryUnescape(filePath)
		_, err := os.Stat(sourcePath2)
		flag = err == nil || os.IsExist(err)
		if flag {
			return true, sourcePath2
		}
		return false, filePath
	}
	return true, filePath
}

// 判断并新建文件夹
func checkDir(dirPath string) error {
	// 使用Stat来检查目录是否存在
	if _, err := os.Stat(dirPath); os.IsNotExist(err) {
		// 目录不存在,使用MkdirAll创建
		err := os.MkdirAll(dirPath, os.ModePerm)
		if err != nil {
			return err
		}
	}
	return nil
}

调用ChangeDir()方法,传入笔记的根目录即可一键整理。

func main() {
	rootPath := "D:/AStudy/typora"
	ChangeDir(rootPath)
}

以下main函数方法会把控制台内容输出到文件中,方便整理失效/移动失败的图片:

// 移动照片
func main() {
	// 打开文件
	file, err := os.OpenFile("output.txt", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
	if err != nil {
		fmt.Println("Error opening file:", err)
		return
	}
	defer file.Close() // 确保文件在结束时关闭
	// 保存原始的输出
	origStdout := os.Stdout
	// 将输出重定向到文件
	os.Stdout = file

	rootPath := "D:/AStudy/副本/typora - 副本/mudi"
	ChangeDir(rootPath)

	// 恢复标准输出到原来的位置
	os.Stdout = origStdout
	// 关闭文件
	file.Close()
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值