清理markdown文件中不使用的图片

清理markdown文件中不使用的图片

起因

使用markdown记录学习笔记,发现markdown删除掉不使用的图片后,只是删除了md文件中对图片的引用,图片依旧保留在文件夹中。
在频繁修改md文件时,不使用的图片会越来越多,占用磁盘空间,所以想把不再使用的图片全部删除。
已经有网友实现了这个功能,我为了锻炼下自己的golang的代码能力,所以就自己又实现了一遍。

实现流程

推荐一个markdown编辑软件,目前依旧开源免费。markText
首先,通过配置文件提供md文件和img文件存储的目录。配置文件名叫”config.json“

{
    "mddir":"your markdown file directory",
    "imgdir":"your img file directory"
}

img目录存储md文件中用到的图片。
实现过程如下:

  1. 读取配置文件,获取md和img的存储目录
  2. 遍历md目录,找到所有的markdown文件
  3. 对于每一个md文件
  4. 找到文件中的”img.*png“的字符串,认为是图片文件名,并记录到mapUsedPng
  5. 所有md文件处理完
  6. 遍历img目录,记录所有的png图片到mapAllpng中
  7. 将正在使用的png从mapAllpng删除,就得到了md文件中未使用的图片
  8. 将img中未使用的图片删除

代码实现

我最熟悉c语言,golang是我最近学习的,所以代码中的C语言的气息会比较浓重,将就着看吧。

package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"os"
	"regexp"
	"strings"
)

type cofigFile struct {
	MDdir  string `json:"mddir"`
	ImgDir string `json:"imgdir"`
}

var configForMd cofigFile
var mapPngUsedString map[string]int = make(map[string]int)
var mapPngAll map[string]int = make(map[string]int)
var mdfileList = make([]string, 0)


func main() {
	//获取Markdown文件和img文件存储的路径
	getConfigFile("./config.json")
	//遍历markdown文件夹,找到所有md文件
	scanMDdir(configForMd.MDdir)

	fmt.Println("len(mdfileList):", len(mdfileList))
	for index := 0; index < len(mdfileList); index++ {
		mdfileName := mdfileList[index]
		fmt.Println("scan mdfile[", index, "]:", configForMd.MDdir+mdfileName)
		inputFile, inputError := os.Open(configForMd.MDdir + mdfileName)
		if inputError != nil {
			fmt.Printf("An error occurred on opening the inputfile\n" +
				"Does the file exist?\n" +
				"Have you got acces to it?\n")
			return // exit the function on error
		}
		defer inputFile.Close()

		inputReader := bufio.NewReader(inputFile)
		for {
			inputString, readerError := inputReader.ReadString('\n')
			//fmt.Printf("The input was: %s", inputString)
			if readerError == io.EOF {
				break
			}
			// 使用正则表达式,寻找png的路径和文件名,
			matchStr, _ := regFindImg(inputString)
			// 将寻找到的在使用的png的文件名记录到map中
			storePngUsedfile(matchStr)
		}
	}

	for k, _ := range mapPngUsedString {
		fmt.Println("used:", k)
	}

	// 将img目录下的png文件名记录到mapPngAll中
	getPngALL(configForMd.ImgDir)

	for k, _ := range mapPngAll {
		fmt.Println("all png:", k)
	}
	// 过滤掉没有使用的png图片文件名
	filterUnusedPngFile()
	// 删除掉未使用的png图片
	deleteUnusedPng(configForMd.ImgDir)
	//等待用户输入,以便看到过程中的打印
	var temp int
	fmt.Scanln(&temp)
}

// 遍历markdown文件夹下,找到所有Markdown文件
func scanMDdir(mddirPath string) {

	fileinfo, err := os.Open(mddirPath)
	if err != nil {
		return
	}
	files, err := fileinfo.Readdir(-1)
	fileinfo.Close()
	if err != nil {
		return
	}

	for _, file := range files {
		//fmt.Println("mddir:", file.Name())
		if !file.IsDir() && regFindmd(file.Name()) {
			mdfileList = append(mdfileList, file.Name())

			fmt.Println("mdfile:", file.Name())

		}

	}
}

func regFindmd(filename string) bool {
	if strings.HasSuffix(filename, ".md") {
		return true
	} else {
		return false
	}
}

// 删除掉未使用的png图片
func deleteUnusedPng(imgdir string) {
	for filename, _ := range mapPngAll {
		delfinename := imgdir + filename
		fmt.Println("del file:", delfinename)
		os.Remove(delfinename)
	}
}

// 过滤掉没有使用的png图片文件名
func filterUnusedPngFile() {

	for allpng, _ := range mapPngAll {
		if _, ok := mapPngUsedString[allpng]; ok {
			fmt.Println(allpng, "is used")
			delete(mapPngAll, allpng)
		}
	}
}

// 将img目录下的png文件名记录到mapPngAll中
func getPngALL(dirpath string) {
	files, err := os.Open(dirpath) //open the directory to read files in the directory
	if err != nil {
		fmt.Println("error opening directory:", err) //print error if directory is not opened
		return
	}
	defer files.Close() //close the directory opened

	fileInfos, err := files.Readdir(-1) //read the files from the directory
	if err != nil {
		fmt.Println("error reading directory:", err) //if directory is not read properly print error message
		return
	}
	for _, fileInfos := range fileInfos {
		//fmt.Println("img dir:", fileInfos.Name()) //print the files from directory
		mapPngAll[fileInfos.Name()] = 1
	}

}

// 获取Markdown文件和img文件存储的路径
func getConfigFile(filepath string) {
	file, err := os.ReadFile(filepath)
	if err != nil {
		log.Fatal(err)
	}

	err = json.Unmarshal(file, &configForMd)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("mddir:", configForMd.MDdir)
	fmt.Println("pngdir:", configForMd.ImgDir)
	
	configForMd.MDdir += "\\"
	configForMd.ImgDir += "\\"
}

// 将寻找到的在使用的png的文件名记录到map中
func storePngUsedfile(matchStr []string) {
	strlength := len(matchStr)
	for i := 0; i < strlength; i++ {
		//寻找到的字符串是”img/.*png“,比如”img/test.png“,
		//实际需要存储的文件名是”test.png“,
		//所以实际存储的字符串要去除前四个字符,实际存储是matchStr[i][4:]
		mapPngUsedString[matchStr[i][4:]] = 1
	}
}

// 使用正则表达式,寻找png的路径和文件名,并通过match数组返回
func regFindImg(content string) (match []string, err error) {

	re := regexp.MustCompile("img/.*png")

	found := re.FindAllString(content, -1)

	if found == nil {
		//fmt.Printf("no match found\n")
		return nil, err
	}

	//fmt.Printf("------found: %q\n", found)

	return found, nil
}

注意事项

1、推荐的md和img的存储结构如下,
|–任意一个目录,假设为A
    ~~~    |—001.md
    ~~~    |—002.md
    ~~~    ****
    ~~~    |—xxx.md
    ~~~    |—img
       ~~~~~~       |— used001.png
       ~~~~~~       |— used002.png
最好将md的图片存储路径放到当前目录的img目录,
如果img存储了其他路径B dir的md文件的图片,就无法知道B路径使用了哪些图片,就会误删除B路径的md文件存储在A路径的img图片。

2、Marktext设置md的图片存储路径的设置如下:
在这里插入图片描述

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值