问题
i need to print events on a folder with multiple subfolders. how to do it recursivly? Please print a c++ code. I am stucked!! Every time the evet is poped i need to open the subfolder, take the file and copy it into another directory. I don't want to list all the subfolders in every 2 seconds and find the files if there are any. Is not efficient. I need to use a monitor folder. Please help
The director that i want to monitor has multiple subfolders. Each subfolder has another subfolder that could contain in a moment of time a file. MainFolder->Subfolders->each subfolder-> subfolder -> file.
Here is the code I have for he moment:
/*
*/
#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include <sys/inotify.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
using namespace std;
vector<string> SS;
void *print_message_function( void *ptr );
int main(int argc, char **argv ){
pthread_t t1;
int fd,fd1,wd,wd1,i=0,i1=0,len=0,len1=0;
int length;
char pathname[100],buf[1024],buf1[1024];
int data;
struct inotify_event *event;
char *message1 = "Thread 1";
FILE *fr;
// fd=inotify_init1(IN_NONBLOCK);//--rewrite
fd = inotify_init();
/* watch /test directory for any activity and report it back to me */
wd=inotify_add_watch(fd,"/home/MainFoder/",IN_ALL_EVENTS);
// int flag=0;
// char*ev="";
//wd=inotifytools_watch_recursively_with_exclude("/home/MainFolder/",IN_ALL_EVENTS);
while(1)
{
//sleep(30);
//read 1024 bytes of events from fd into buf
i=0;
len=read(fd,buf,1024);
while(i<len){
event=(struct inotify_event *) &buf[i];
/* watch /test directory for any activity and report it back to me */
/* check for changes */
{
if((event->mask & IN_OPEN) ||(event->mask & IN_CREATE))
{
printf("\n %s :was opened\n",event->name);
SS.push_back(event->name);
}
}
/* update index to start of next event */
i+=sizeof(struct inotify_event)+event->len;
}
vector<string>::const_iterator cii;
for(cii=SS.begin(); cii!=SS.end(); cii++)
{
wd1 = watch_from_filename(*ci);
}
/*
vector<string>::const_iterator cii;
for(cii=SS.begin(); cii!=SS.end(); cii++)
{
cout <<"HERE:"<< *cii << endl;
}
*/
int iret1, iret2;
/* Create independent threads each of which will execute function */
iret1 = pthread_create( &t1, NULL, print_message_function, (void*) message1);
}
}
void *print_message_function( void *ptr )
{
vector<string>::const_iterator cii;
for(cii=SS.begin(); cii!=SS.end(); cii++)
{
cout <<"HERE:"<< *cii << endl;
std::string path=exec
}
}
回答1:
This working sample on Github does what you're looking for: inotify-example.cpp
On CREATE events, the current wd (watch descriptor), plus the inotify_event wd and name components, are added to a Watch object (see sample). The class includes methods to lookup wd and names in several ways.
This snippet shows how CREATE/DELETE events are handled:
if ( event->mask & IN_CREATE ) {
current_dir = watch.get(event->wd);
if ( event->mask & IN_ISDIR ) {
new_dir = current_dir + "/" + event->name;
wd = inotify_add_watch( fd, new_dir.c_str(), WATCH_FLAGS );
watch.insert( event->wd, event->name, wd );
total_dir_events++;
printf( "New directory %s created.\n", new_dir.c_str() );
} else {
total_file_events++;
printf( "New file %s/%s created.\n", current_dir.c_str(), event->name );
}
} else if ( event->mask & IN_DELETE ) {
if ( event->mask & IN_ISDIR ) {
new_dir = watch.erase( event->wd, event->name, &wd );
inotify_rm_watch( fd, wd );
total_dir_events--;
printf( "Directory %s deleted.\n", new_dir.c_str() );
} else {
current_dir = watch.get(event->wd);
total_file_events--;
printf( "File %s/%s deleted.\n", current_dir.c_str(), event->name );
}
}
回答2:
You can do it in two steps:
- Detect all the changes you're interested in on the root directory, plus (if not already included) creations (
IN_CREATE
). - If the creation is a directory, do the whole algorithm on it.
回答3:
I have written the code for you. Now, you have to do only one change in this code. Just give path of your directory in main function.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <limits.h>
#include<sys/stat.h>
#include<dirent.h>
#include<time.h>
#include<string.h>
#include<unistd.h>
#define MAX_EVENTS 1024 /*Max. number of events to process at one go*/
#define LEN_NAME 16 /*Assuming that the length of the filename won't exceed 16 bytes*/
#define EVENT_SIZE ( sizeof (struct inotify_event) ) /*size of one event*/
#define BUF_LEN ( MAX_EVENTS * ( EVENT_SIZE + LEN_NAME )) /*buffer to store the data of events*/
void monitor(char *);
int evnt_mon(char *);
void main()
{
if(fork()==0)
evnt_mon("./usssb");// give path of your directory which you want to monitor
monitor("./usssb");// give path of your directory which you want to monitor
while(1);
}
void monitor(char * rt_dir)
{
struct stat st;
DIR *dirp;
struct dirent *dp;
char str[100][100]={ };
char temp[100];
char str1[500]=" ";
int i=0,j=0,src_ret=9,src_ret1=9;
strcpy(str1,rt_dir);
dirp=opendir(str1);
if(dirp==NULL)
{
perror("opendir");
return;
}
while(1)
{
dp=readdir(dirp);
if(dp==NULL)
break;
if((strcmp(dp->d_name,".\0")==0) || (strcmp(dp->d_name,"..")==0))
continue;
if((dp->d_type==DT_DIR)&&((strcmp(dp->d_name,".")!=0)&&(strcmp(dp->d_name,"..")!=0)))
{
strcat(str[i],str1);
strcat(str[i],"/");
strcat(str[i],dp->d_name);
if(fork()==0)
{
evnt_mon(str[i]);
}
i++;
}
}
closedir(dirp);
if(i>0)
{
for(j=0;j<i;j++)
{
monitor(str[j]);
}
}
}
int evnt_mon(char *argv)
{
int length, i = 0, wd;
int fd;
char buffer[BUF_LEN];
/* Initialize Inotify*/
fd = inotify_init();
if ( fd < 0 )
{
perror( "Couldn't initialize inotify");
}
/* add watch to starting directory */
wd = inotify_add_watch(fd, argv, IN_CREATE | IN_MODIFY | IN_DELETE);
if (wd == -1)
{
printf("Couldn't add watch to %s\n",argv);
}
else
{
printf("Watching:: %s\n",argv);
}
/* do it forever*/
while(1)
{
i = 0;
length = read( fd, buffer, BUF_LEN );
if ( length < 0 )
{
perror( "read" );
}
while ( i < length )
{
struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
if ( event->len )
{
if ( event->mask & IN_CREATE)
{
if (event->mask & IN_ISDIR)
{
printf( "The directory %s was Created in %s.\n", event->name,argv );
if(fork()==0)
{
char p[100]=" ";
strcpy(p,argv);
strcat(p,"/");
strcat(p,event->name);
evnt_mon(p);
}
}
else
printf( "The file %s was Created with WD %d\n", event->name, event->wd );
}
if ( event->mask & IN_MODIFY)
{
if (event->mask & IN_ISDIR)
printf( "The directory %s was modified.\n", event->name );
else
printf( "The file %s was modified with WD %d\n", event->name, event->wd );
}
if ( event->mask & IN_DELETE)
{
if (event->mask & IN_ISDIR)
printf( "The directory %s was deleted from %s.\n", event->name,argv );
else
printf( "The file %s was deleted with WD %d\n", event->name, event->wd );
}
i += EVENT_SIZE + event->len;
}
}
}
/* Clean up*/
inotify_rm_watch( fd, wd );
close( fd );
return 0;
}
回答4:
To address the problem stated by ribram (the 'hole':)). one possible solution i can think of is that we can do a combination of 'polling the directory' and 'using inotify'... i.e. Each time a directory is detected (directory only, don't do it for files):
- add a watchpoint for the newly detected directory to inotify
- 'poll' (or 'scan') the newly detected directory (man readdir()) to see if there're already items (files, directories) created. Those are possibly the ones that are missing.
Note that to build an 'air-tight' case, the above steps' order is important. you need to add the watchpoint first than scan ... This will guarantee that an item is picked up by either 'scan' or inotify or both. In that case you may also need to aware of the dups. i.e. the same item can be both yielded by the scan and the inotify
回答5:
You might use the fanotify API. It allows you to monitor a complete mount. The only drawback is that you need to be root.
来源:https://stackoverflow.com/questions/9147757/inotify-recursively-how-to-do-it