Monitor directory for new files only

2019-04-12 19:58发布

问题:

I'd like to monitor a directory for new files from a C app. However, I'm not interested in modified files, only in new files. Currently I'm using readdir/stat for that purpose:

while ( (ent = readdir(dir)) != NULL ) {
  strcpy(path, mon_dir);
  strcat(path, "/");
  strcat(path, ent->d_name);
  if ( stat(path, &statbuf) == -1 ) {
    printf( "Can't stat %s\n", ent->d_name );
    continue;
  }
  if ( S_ISREG(statbuf.st_mode) ) {
    if ( statbuf.st_mtime > *timestamp ) {
      tcomp = localtime( &statbuf.st_mtime );
      strftime( s_date, sizeof(s_date), "%Y%m%d %H:%M:%S", tcomp );
      printf( "%s %s was added\n", s_date, ent->d_name );
      *timestamp = statbuf.st_mtime;
    }
  }
}

Any idea how I can detect newly created files on Linux AND Solaris 10 without keeping a list of files?

Cheers,

Martin.

回答1:

gamin provides an abstraction around system dependant file notification apis for many *nixes , and it's included in many linux distros by default.

For linux, you could use the linux specific inotify api.

Win32 has a similar API via FindFirstChangeNotification



回答2:

The solution is to store the last access time in a global variable and pick the latest files with a filter to scandir():

int cmp_mtime( const struct dirent** lentry, const struct dirent** rentry ):

  1. Stat (*lentry)->d_name (extended by path, but that's a detail only)
  2. ltime = statbuf.st_mtime;
  3. Stat (*rentry)->d_name (extended by path, but that's a detail only)
  4. rtime = statbuf.st_mtime;
  5. if ( ltime < rtime ) return -1;
  6. else if ( ltime > rtime ) return 1;
  7. return 0;

int selector( const struct dirent* entry ):

  1. Stat entry->d_name (extended by path, but that's a detail only)
  2. If not normal file then return 0
  3. If stat.st_mtime > lastseen then return 1 else return 0

Main:

  1. Init global time variable lastseen
  2. scandir( directory, &entries, selector, cmp_mtime );
  3. Process list of entries
  4. lastseen := mtime of last entry in list


回答3:

There is probably no better way with Solaris 10 outside interfacing with either the dtrace command or libdtrace (not recommended). On SunOS 5.11 based OSes (eg: OpenSolaris, Solaris 11 Express, ...), you can just use the File Event Notification framework.



回答4:

On MacOS X there is a file monitoring API and the provided sample code shows how to find which files have changed.



回答5:

You could use FAM - File Alteration Monitor for this.



回答6:

one trick may be to set the archive bit for handled files.

Edith says: if nothing else from the other answeres helpes, you may play with chmod() instead.



回答7:

Was researching the same topic on Solaris and found the example of the watchdir app, to be used from within scripts, as in

watchdir /foo/bar

which will perform a blocking wait until something happens on the watched directory.

Link: https://solarisrants.wordpress.com/2013/07/24/solaris-file-event-notification/



回答8:

I know you were asking for a solution from C but in fact Java (now) has a cross-platform class for this. You can read more about it here. Also see documentation for the WatchService class which is the central class of Java's file change notification ability.

Perhaps there's some documentation somewhere as to how Java accomplishes this on the various platforms ?

From the little I understand Java uses the OS's native file change notification API on Linux, Solaris and Windows and then in addition also implements a fallback method which is based on polling and which will work on any platform.