递归地inotify怎么做呢?

发布于 2025-01-02 04:27:53 字数 2850 浏览 1 评论 0原文

我需要在具有多个子文件夹的文件夹上打印事件。如何递归地做到这一点?请打印 C++ 代码。我被困住了!每次弹出 evet 时,我都需要打开子文件夹,获取文件并将其复制到另一个目录中。我不想每 2 秒列出所有子文件夹并查找文件(如果有)。效率不高。我需要使用监视器文件夹。请帮助

我想要监控的导演有多个子文件夹。每个子文件夹都有另一个子文件夹,其中可能包含一个文件。主文件夹->子文件夹->每个子文件夹->子文件夹->文件。

这是我现在的代码:

/*


*/
  #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

       }
}

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

       }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

美男兮 2025-01-09 04:27:53

Github 上的这个工作示例可以满足您的需求:inotify-example.cpp

On CREATE 事件、当前 wd(监视描述符)以及 inotify_event wd 和名称组件,被添加到 Watch 对象(参见示例)。
该类包含以多种方式查找 wd 和名称的方法。

此代码片段显示了如何处理 CREATE/DELETE 事件:

            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 );
                }
            }

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 );
                }
            }
蒲公英的约定 2025-01-09 04:27:53

您可以分两步完成:

  1. 检测根目录上您感兴趣的所有更改,以及(如果尚未包含)创建内容 (IN_CREATE)。
  2. 如果创建的是一个目录,则对其执行整个算法。

You can do it in two steps:

  1. Detect all the changes you're interested in on the root directory, plus (if not already included) creations (IN_CREATE).
  2. If the creation is a directory, do the whole algorithm on it.
两个我 2025-01-09 04:27:53

我已经为你写了代码。现在,您只需对此代码进行一项更改。只需在主函数中给出目录的路径即可。

#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;
}

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;
}
念三年u 2025-01-09 04:27:53

您可以使用 fanotify API。它允许您监控完整的安装。唯一的缺点是你需要 root。

You might use the fanotify API. It allows you to monitor a complete mount. The only drawback is that you need to be root.

笨笨の傻瓜 2025-01-09 04:27:53

解决 ribram 提出的问题(“洞”:))。我能想到的一个可能的解决方案是,我们可以结合使用“轮询目录”和“使用 inotify”...即每次检测到目录时(仅限目录,不要对文件执行此操作):

  • 添加新检测到的目录的观察点,以 inotify
  • “轮询”(或“扫描”)新检测到的目录(man readdir())以查看是否已创建项目(文件、目录)。这些可能是缺失的。

请注意,要构建“密不透风”的外壳,上述步骤的顺序很重要。您需要先添加观察点而不是扫描...这将保证“扫描”或 inotify 或两者都拾取项目。在这种情况下,您可能还需要了解重复项。即相同的项目可以通过扫描和 inotify 产生

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文