Golang在macOS上使用Fsnotify的实践指南

Golang在macOS上使用Fsnotify的实践指南 我正在尝试在 macos 上使用 fsnotify 创建一个目录监视器。在测试中,我注意到当我删除文件时,收到的是 重命名 事件通知,而不是删除 事件。请问我是否遗漏了什么?

以下代码基于 example_test.go

package main

import (
	"log"

	"github.com/fsnotify/fsnotify"
)

func main() {
	ExampleNewWatcher()
}

func ExampleNewWatcher() {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	defer watcher.Close()

	done := make(chan bool)
	go func() {
		for {
			select {
			case event := <-watcher.Events:
				log.Println("event:", event)
			case err := <-watcher.Errors:
				log.Println("error:", err)
			}
		}
	}()

	err = watcher.Add("/Users/blabla/go/src/sync")
	if err != nil {
		log.Fatal(err)
	}
	<-done
}

感谢您的帮助!


更多关于Golang在macOS上使用Fsnotify的实践指南的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

你的测试是做什么的?(在Finder中删除文件只是将文件重命名到垃圾箱中…)

更多关于Golang在macOS上使用Fsnotify的实践指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你的测试做什么? 它应该在调用移除事件时调用回调函数。

这是你测试的预期结果,而不是测试实际执行的操作——即测试过程。

如果在Finder中删除文件只是一个重命名操作,那么有没有办法知道文件是真正被删除还是被重命名了?

在 macOS 上使用 fsnotify 时,删除文件触发重命名事件而非删除事件是正常行为。这是因为 macOS 的文件系统事件机制(基于 FSEvents API)在某些情况下会将文件删除操作解释为重命名事件,特别是当文件被移动到回收站(.Trash 目录)时。以下是对代码的修改,以正确处理这种情况:

package main

import (
	"log"
	"strings"

	"github.com/fsnotify/fsnotify"
)

func main() {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	defer watcher.Close()

	done := make(chan bool)
	go func() {
		for {
			select {
			case event := <-watcher.Events:
				log.Println("event:", event)
				// 检查事件类型,处理 macOS 上的删除事件
				if event.Op&fsnotify.Remove == fsnotify.Remove {
					log.Printf("File removed: %s", event.Name)
				} else if event.Op&fsnotify.Rename == fsnotify.Rename {
					// 在 macOS 上,删除文件可能触发重命名事件
					// 检查文件是否不再存在,以确认删除
					log.Printf("Rename event (potential delete): %s", event.Name)
				}
			case err := <-watcher.Errors:
				log.Println("error:", err)
			}
		}
	}()

	err = watcher.Add("/Users/blabla/go/src/sync")
	if err != nil {
		log.Fatal(err)
	}
	<-done
}

如果需要在 macOS 上更可靠地检测文件删除,可以结合检查文件是否存在:

package main

import (
	"log"
	"os"

	"github.com/fsnotify/fsnotify"
)

func main() {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	defer watcher.Close()

	done := make(chan bool)
	go func() {
		for {
			select {
			case event := <-watcher.Events:
				log.Println("event:", event)
				if event.Op&fsnotify.Rename == fsnotify.Rename {
					// 检查文件是否已删除
					if _, err := os.Stat(event.Name); os.IsNotExist(err) {
						log.Printf("File deleted: %s", event.Name)
					}
				}
			case err := <-watcher.Errors:
				log.Println("error:", err)
			}
		}
	}()

	err = watcher.Add("/Users/blabla/go/src/sync")
	if err != nil {
		log.Fatal(err)
	}
	<-done
}

这些修改利用了 fsnotify 的事件类型和文件系统检查,以适应 macOS 的行为。

回到顶部