[ACCEPTED]-Is there an equivalent to the .Net FileSystemWatcher in the Linux world?-file-io

Accepted answer
Score: 15

I would like to share my observations using 22 FileSystemWatcher in Mono in Ubuntu 10.10. Here 21 is a very simple implementation of FileSystemWatcher 20 in C#

using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.IO;
using System.Reflection;

namespace FileSystemWatcherSandbox
{
    public class Program
    {
        static void Main(string[] args)
        {
            foreach(DictionaryEntry de in Environment.GetEnvironmentVariables())
            {
                Console.WriteLine("{0} = {1}",de.Key,de.Value);
            }
            string basePath = AppDomain.CurrentDomain.BaseDirectory;
            Console.WriteLine("watching: {0}", basePath);
            FileSystemWatcher fsw = new FileSystemWatcher(basePath);
            fsw.Changed += new FileSystemEventHandler(fsw_Changed);
            fsw.Created += new FileSystemEventHandler(fsw_Created);
            fsw.Deleted += new FileSystemEventHandler(fsw_Deleted);
            fsw.Error += new ErrorEventHandler(fsw_Error);
            fsw.Renamed += new RenamedEventHandler(fsw_Renamed);
            fsw.EnableRaisingEvents = true;
            fsw.IncludeSubdirectories = true;
            while (true)
            {
                WaitForChangedResult result = fsw.WaitForChanged(WatcherChangeTypes.All,10000);
                Console.WriteLine(result.TimedOut ? "Time out" : "hmmm");
            }
        }

        static void fsw_Renamed(object sender, RenamedEventArgs e)
        {
            Console.WriteLine("({0}): {1} | {2}", MethodInfo.GetCurrentMethod().Name, e.ChangeType, e.FullPath);
        }

        static void fsw_Error(object sender, ErrorEventArgs e)
        {
            Console.WriteLine("({0}): {1}", MethodInfo.GetCurrentMethod().Name, e.GetException().Message);
        }

        static void fsw_Deleted(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine("({0}): {1} | {2}", MethodInfo.GetCurrentMethod().Name, e.ChangeType, e.FullPath);
        }

        static void fsw_Created(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine("({0}): {1} | {2}", MethodInfo.GetCurrentMethod().Name, e.ChangeType, e.FullPath);
        }

        static void fsw_Changed(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine("({0}): {1} | {2}", MethodInfo.GetCurrentMethod().Name, e.ChangeType, e.FullPath);
        }
    }
}

This code was tested and works on both 19 Windows XP and Ubuntu 10.10. However, I 18 would like to point out that under Ubuntu 17 10.10 (possibly earlier versions as well), the 16 FileSystemWatcher behaves uniquely.
If the 15 directory that is being watched does not 14 contain subdirectories, then invoking a 13 FileSystemWatcher with the IncludeSubdirectories 12 property set to true will result in the 11 FileSystemWatcher ignoring events. However, if 10 there are subdirectories in the target directory, then 9 IncludeSubdirectories set to true will work 8 as expected.
What will always work is if 7 IncludeSubdirectories is set to false. In 6 this instance, the FileSystemWatcher will 5 only be watching the target directory.
I 4 hope this is useful for programmers that 3 would like to utilize Mono across different 2 operating systems and invoke the FileSystemWatcher 1 type.

Score: 14

That would be Gamin the File Alteration Monitor or Inotify.

Edit: Mono does have 19 Gamin bindings - in fact, its implementation 18 of FileSystemWatcher uses Gamin. https://www.mono-project.com/docs/faq/technical/#what-are-the-issues-with-filesystemwatcher.

What are the issues with FileSystemWatcher?

The Mono 17 implementation of FileSystemWatcher has 16 a number of backends, the most optimal one, the 15 one with fewer dependencies is the inotify-backend 14 (available in Mono 1.1.17 and newer versions).

With 13 this backend the kernel provides Mono with 12 updates on any changes to files on the file 11 system but it requires an inotify-enabled 10 kernel, which only newer Linux distributions 9 ship.

In older Linux systems, you must have 8 installed FAM or Gamin (it will work with 7 either one). You might need the -devel packets 6 installed.

For the *BSD family, there’s a 5 Kqueue based implementation that will be 4 used when detected at runtime.

If none of 3 the above work, Mono falls back to polling 2 the directories for changes, which far from 1 optimal.

Score: 6

As has already being said, Mono has the 21 class "System.IO.FileSystemWatcher", this 20 is the relevant link: http://www.go-mono.com/docs/monodoc.ashx?link=T%3aSystem.IO.FileSystemWatcher

"Mono's implementation 19 of the FileSystemWatcher has multiple backends. This 18 is necessary because not all operating 17 systems supported by Mono have all the 16 features necessary to provide the functionality 15 expected by applications.

If the operating 14 system kernel supports watching directories 13 (inotify on Linux, KEvents on BSD or OSX) that feature 12 is used; Otherwise it falls back to using 11 the Gamin or FAM libraries (these libraries 10 provide an API to monitor directories) and 9 if none of those features are available, Mono 8 will poll every 750 milliseconds the directories 7 watched.

You can force the polling behavior (instead 6 of using the kernel support) by setting 5 the MONO_MANAGED_WATCHER environment variable 4 before executing your application. This 3 might be useful for filesystems that do 2 not support inotify and still require 1 polling to detect changes."

Score: 2

Yes, dnotify and inotify.

I don't know if Mono has 1 these wrapped, but it would be worth checking.

Score: 2

If you're using the wonderful QT library 2 (www.qtsoftware.com) it's included as the 1 QFileSystemWatcher.

More Related questions