Created
June 4, 2024 10:27
-
-
Save peteretelej/451563bac429dd75cdcd447a60c94186 to your computer and use it in GitHub Desktop.
Fix Obsidian Pasted Image Locations - update to attachments folder
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Cleanup old Obsidian Pasted Image links | |
// Finds all images and moves them to an `attachments/` folder in the same directory as the markdown linking it | |
// and then deletes the old images. | |
package main | |
import ( | |
"bytes" | |
"fmt" | |
"log" | |
"os" | |
"path/filepath" | |
"regexp" | |
"strings" | |
"sync" | |
) | |
var cwd = "" | |
func main() { | |
cwd, _ = os.Getwd() | |
fmt.Println("Cleaning up attachments in ", cwd) | |
files := findMarkdownFiles(".") | |
var wg sync.WaitGroup | |
wg.Add(len(files)) | |
deleteImagesChan := make(chan string) | |
for _, f := range files { | |
go func(wg *sync.WaitGroup, f string, deleteImagesChan chan string) { | |
if err := fixPastedImage(f, deleteImagesChan); err != nil { | |
fmt.Printf("\n%s Error: %v\n", f, err) | |
} | |
wg.Done() | |
}(&wg, f, deleteImagesChan) | |
} | |
go func() { | |
wg.Wait() | |
close(deleteImagesChan) | |
}() | |
for img := range deleteImagesChan { | |
if _, err := os.Stat(img); err == os.ErrNotExist { | |
continue | |
} | |
if err := os.Remove(img); err != nil { | |
fmt.Println("Error deleting image: ", img) | |
} | |
} | |
} | |
func findMarkdownFiles(root string) []string { | |
var files []string | |
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { | |
if err != nil { | |
return err | |
} | |
// Skip directories prefixed with a dot | |
if info.IsDir() && len(info.Name()) > 2 && strings.HasPrefix(info.Name(), ".") { | |
return filepath.SkipDir | |
} | |
// Check if the file has a .md extension | |
if !info.IsDir() && strings.HasSuffix(info.Name(), ".md") { | |
files = append(files, path) | |
} | |
return nil | |
}) | |
if err != nil { | |
log.Fatal(err) | |
} | |
return files | |
} | |
var imageRegexp = regexp.MustCompile(`!\[\[Pasted image \d+.png\]\]`) | |
func fixPastedImage(file string, deleteImagesChan chan string) error { | |
dir := filepath.Dir(file) | |
dat, err := os.ReadFile(file) | |
if err != nil { | |
return err | |
} | |
if !bytes.Contains(dat, []byte("![[Pasted image")) { | |
return nil | |
} | |
if _, err := os.Stat(dir + "/attachments"); err != nil && os.IsNotExist(err) { | |
if err := os.Mkdir(dir+"/attachments", os.ModePerm); err != nil { | |
return err | |
} | |
} | |
matches := imageRegexp.FindAllStringSubmatch(string(dat), -1) | |
if matches == nil { | |
return fmt.Errorf("no image matches found") | |
} | |
content := string(dat) | |
for _, match := range matches { | |
fileName := strings.TrimRight(strings.TrimLeft(match[0], "![["), "]]") | |
src, err := findMarkdownAttachment(dir, fileName) | |
if err != nil { | |
log.Printf("%s - Error: %v", file, err) | |
continue | |
} | |
dst := filepath.Join(dir, "attachments", fileName) | |
if err := copyFile(src, dst); err != nil { | |
log.Printf("%s - Error: %v", file, err) | |
continue | |
} | |
deleteImagesChan <- src // flag for deletion | |
oldReference := fmt.Sprintf("![[%s]]", fileName) | |
newReference := fmt.Sprintf("", filepath.Base(fileName)) | |
content = strings.ReplaceAll(content, oldReference, newReference) | |
} | |
err = os.WriteFile(file, []byte(content), 0644) | |
if err != nil { | |
return err | |
} | |
log.Printf("fixed: %s", file) | |
return nil | |
} | |
// findMarkdownAttachment finds the image location, can be in same directory or parent directory | |
func findMarkdownAttachment(dir, fileName string) (string, error) { | |
mainDirFile := filepath.Join(cwd, fileName) | |
currentDirFile := filepath.Join(dir, fileName) | |
if _, err := os.Stat(mainDirFile); err == nil { | |
return mainDirFile, nil | |
} | |
if _, err := os.Stat(currentDirFile); err == nil { | |
return currentDirFile, nil | |
} | |
return "", fmt.Errorf("file not found - %s", fileName) | |
} | |
func copyFile(src, dst string) error { | |
input, err := os.ReadFile(src) | |
if err != nil { | |
return err | |
} | |
err = os.WriteFile(dst, input, 0644) | |
if err != nil { | |
return err | |
} | |
return nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment