等待文件复制完成

时间:2018-07-29 01:24:15

标签: linux file go

我正在使用golang watcher软件包来监视文件目录。 https://github.com/radovskyb/watcher

唯一的问题是,创建事件是在文件开始被复制/移动时触发的,而不是在文件实际就绪时触发的。我想知道在创建事件之后Go中是否有一种整洁的等待方式,直到不再写入文件再继续。

我想这种等待很可能必须在goroutine中完成才能不阻止任何其他文件事件。

简单的例子:

package main

import (
        "fmt"
        "log"
        "time"

        "github.com/radovskyb/watcher"
)

func main() {
        w := watcher.New()

        w.FilterOps(watcher.Create, watcher.Write)

        go func() {
                for {
                        select {
                        case event := <-w.Event:
                                fmt.Println(event) // Print the event's info.
                                if event.Op == watcher.Create {
                                    // HERE WE DO STUFF
                                    doStuff(event)
                                }
                        case err := <-w.Error:
                                log.Fatalln(err)
                        case <-w.Closed:
                                return
                        }
                }
        }()

        // Watch this folder for changes.
        if err := w.Add("./files/"); err != nil {
                log.Fatalln(err)
        }


        // Start the watching process - it'll check for changes every 100ms.
        if err := w.Start(time.Millisecond * 100); err != nil {
                log.Fatalln(err)
        }
}

谢谢!

2 个答案:

答案 0 :(得分:2)

您正在使用的库无法完成您要问的事情。文档说:

  

watcher是一个Go程序包,用于(递归或非递归地)监视文件或目录更改(<递归>而不使用文件系统事件),从而使它可以跨平台一致地工作。

当我第一次看到这个问题时,我认为可以通过等待“文件关闭”事件来轻松解决,该事件将在文件复制完成时发生。但是由于您正在使用的库拒绝使用特定于平台的API,因此它无法了解此信息。

您可以使用inotify来更有效,更准确地解决问题。有https://github.com/fsnotify/fsnotify,但不支持IN_CLOSE_WRITE事件(请参见https://github.com/golang/go/issues/15406)。也许您可以以此为灵感来编写自己的inotify包装器,该包装器确实支持IN_CLOSE_WRITE(可能还很少)。

inotify的一个显着局限性是它不能与NFS一起使用,但是watcher也有局限性(并且您不希望在网络共享上使用其轮询机制。至少不是很快)。

答案 1 :(得分:1)

fkocik提交了实现IN_CLOSE_WRITE的PR,它在Linux上确实对我有用。

ADDED: CloseWrite event support

注意:该代码尚不存在于master分支中,您需要手动检索它。