inotify监听文件夹的变动
inotify只能监控单层目录变化,不能监控子目录中的变化情况。
如果需要监控子目录,需要在调用inotify_add_watch(int fd, char *dir, int mask):int建立监控时,递归建立子目录的监控,伪代码如下
void addwatch(int fd, char *dir, int mask)
{
wd = inotify_add_watch(fd, dir, mask);
向目录集合加入(wd, dir);
for (dir下所有的子目录subdir)
addwatch(fd, subdir, mask);
}
这样就可以得到一个目录集合,其中每一个wd对应一个子目录。
当你调用read获取信息时,可以得到一个下面的结构体
struct inotify_event
{
int wd; /* Watch descriptor. */
uint32_t mask; /* Watch mask. */
uint32_t cookie; /* Cookie to synchronize two events. */
uint32_t len; /* Length (including NULs) of name. */
char name __flexarr; /* Name. */
};
其中,通过event->wd和刚才记录的目录集合可以知道变动的具体子目录。
event->name为具体的文件名称。
event->name是一个char name[0]形式的桩指针,具体的name占据的长度可以由event->len得出 我的监控部分代码如下:
enum {EVENT_SIZE = sizeof(struct inotify_event)};
enum {BUF_SIZE = (EVENT_SIZE + 16) << 10};
void watch_mon(int fd)
{
int i, length;
void *buf;
struct inotify_event *event;
buf = malloc(BUF_SIZE); while ((length = read(fd, buf, BUF_SIZE)) >= 0)
{
i = 0;
while (i < length)
{
event = buf + i;
if (event->len)
具体处理函数(event);
i += EVENT_SIZE + event->len;
}
}
close(fd);
exit(1);
}
在你的具体处理函数中,通过wd辨识子目录,通过name辨识文件 这是利用C++STLmap写的一个范例,可以监视当前目录下(含子目录)的变化,创建,删除过程(新建立的目录不能监视,只能通过监视到创建新目录的事件后重新初始化监视表)
新版1.1.0,可以监视创建的子目录,方法是,当do_action探测到新目录创建的动作时,调用inotify_add_watch追加新的监视
/*
Copyright (C) 2010-2011 LIU An (SuperHacker@china.com.cn) This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <unistd.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <errno.h>
#include <dirent.h> #include <map>
#include <string>
using namespace std; void addwatch(int, char*, int);
static int filter_action(uint32_t mask);
int watch_init(int mask, char *root);
void addwatch(int fd, char *dir, int mask);
static void do_action(int fd, struct inotify_event *event);
void watch_mon(int fd);
static void send_mess(char *name, char *act, int ewd);
void append_dir(int fd, struct inotify_event *event, int mask); map<int, string> dirset; enum{MASK = IN_MODIFY | IN_CREATE | IN_DELETE}; int main(int argc, char **argv)
{
int fd;
if (argc != 2)
{
fprintf(stderr, "Usage: %s dir\n", argv[0]);
exit(1);
} fd = watch_init(MASK, argv[1]);
watch_mon(fd); return 0;
} int watch_init(int mask, char *root)
{
int i, fd; if ((fd = inotify_init()) < 0)
perror("inotify_init");
addwatch(fd, root, mask);
return fd;
} void addwatch(int fd, char *dir, int mask)
{
int wd;
char subdir[512];
DIR *odir;
struct dirent *dent; if ((odir = opendir(dir)) == NULL)
{
perror("fail to open root dir");
exit(1);
}
wd = inotify_add_watch(fd, dir, mask);
dirset.insert(make_pair(wd, string(dir))); errno = 0;
while ((dent = readdir(odir)) != NULL)
{
if (strcmp(dent->d_name, ".") == 0
|| strcmp(dent->d_name, "..") == 0)
continue;
if (dent->d_type == DT_DIR)
{
sprintf(subdir, "%s/%s", dir, dent->d_name);
addwatch(fd, subdir, mask);
}
} if (errno != 0)
{
perror("fail to read dir");
exit(1);
} closedir (odir);
} enum {EVENT_SIZE = sizeof(struct inotify_event)};
enum {BUF_SIZE = (EVENT_SIZE + 16) << 10}; void watch_mon(int fd)
{
int i, length;
void *buf;
struct inotify_event *event;
buf = malloc(BUF_SIZE); while ((length = read(fd, buf, BUF_SIZE)) >= 0)
{
i = 0;
while (i < length)
{
event = (struct inotify_event*)(buf + i);
if (event->len)
do_action(fd, event);
i += EVENT_SIZE + event->len;
}
}
close(fd);
exit(1);
} static char action[][10] =
{
"modified",
"accessed",
"created",
"removed"
}; enum{NEWDIR = IN_CREATE | IN_ISDIR}; static void do_action(int fd, struct inotify_event *event)
{
int ia, i; if ((ia = filter_action(event->mask)) < 0)
return; if ((event->mask & NEWDIR) == NEWDIR)
append_dir(fd, event, MASK); send_mess(event->name, action[ia], event->wd);
} void append_dir(int fd, struct inotify_event *event, int mask)
{
char ndir[512];
int wd; sprintf(ndir, "%s/%s", dirset.find(event->wd)->second.c_str(),
event->name);
wd = inotify_add_watch(fd, ndir, mask);
dirset.insert(make_pair(wd, string(ndir)));
} static int filter_action(uint32_t mask)
{
if (mask & IN_MODIFY)
return 0;
if (mask & IN_ACCESS)
return 1;
if (mask & IN_CREATE)
return 2;
if (mask & IN_DELETE)
return 3;
return -1;
} static void send_mess(char *name, char *act, int ewd)
{
char format[] = "%s was %s.\n";
char file[512]; sprintf(file, "%s/%s", dirset.find(ewd)->second.c_str(), name); printf(format, file, act);
}
inotify监听文件夹的变动的更多相关文章
- 使用Node.JS监听文件夹变化
使用Node.JS监听文件夹改变有许多应用场合,比如: 构建自动编绎工具 当源文件改变时,自动运行build过程,比如当你写CoffeeScript文件或SASS CSS文件时,保存之后可即时生成对应 ...
- nodejs 监听文件夹变化的模块
使用Node.JS监听文件夹变化 fs.watch 其中Node.JS的文件系统也可侦听某个目录的改变, 如fs.watch 其中fs.watch的最大缺点就是不支持子文件夹的侦听,并且在很多情况 ...
- inotify监听文件
inotify监听文件并通知 static int inotify_dbfile(const char *spFromRule, const char *spDevFile) { int inotif ...
- c# 监听文件夹动作
static FileSystemWatcher watcher = new FileSystemWatcher(); /// <summary> /// 初始化监听 ...
- Java_监听文件夹或者文件是否有变动
package org.testWatch.Watch; import java.nio.file.FileSystems; import java.nio.file.Path; import jav ...
- kafka flumn sparkstreaming java实现监听文件夹内容保存到Phoenix中
ps:具体Kafka Flumn SparkStreaming的使用 参考前几篇博客 2.4.6.4.1 配置启动Kafka (1) 在slave机器上配置broker 1) 点击CDH上的kafk ...
- Java_监听器监听文件夹变动
package demo4; import java.io.IOException;import java.nio.file.FileSystems;import java.nio.file.Path ...
- java 监听文件或文件夹变化
今天遇到一个新需求,当从服务器下载文件后用指定的本地程序打开,不知道何时文件下载完成,只能考虑监听文件夹,当有新文件创建的时候打开指定程序. 在此给出一个完整的下载和打开过程: 1.下载文件 jsp页 ...
- 如何使用NodeJs来监听文件变化
1.前言 在我们调试修改代码的时候,每修改一次代码,哪怕只是很小的修改,我们都需要手动重新build文件,然后再运行代码,看修改的效果,这样的效率特别低,对于开发者来说简直不能忍. 2.构建自动编译工 ...
随机推荐
- es6 字符串方法
1.字符串的新方法 includes() 包含属性 startsWith() 头部开始是否包含 endWith() 字符串是否在尾部 ========三个返回值都为布尔值 第二参数为数字 e ...
- 总结一下《vue的使用》
1.用vue创建项目的时候, 1.安装axios,对axios进行处理,创建axios.js文件,设置基础请求地址, 设置前置守卫和独享守卫,对请求数据进行设置,(特别实在进行token验证的时候特别 ...
- UVa 11542 Square (高斯消元)
题意:给定 n 个数,从中选出一个,或者是多个,使得选出的整数的乘积是完全平方数,求一共有多少种选法,整数的素因子不大于 500. 析:从题目素因子不超过 500,就知道要把每个数进行分解.因为结果要 ...
- SQL优化实战之加索引
有朋友和我说他的虚机里面的mysql无法跑sql,但是在本地环境是这个sql是可以跑出来的.碰到这个问题第一反应是:死锁. 于是让他查询数据库的几个状态: 发现连即时锁都非常少,不是锁的问题. 进一步 ...
- AngularJS实战之路由ui-view传参
angular路由传参 首页 <!DOCTYPE html> <html ng-app="app"> <head> <title>路 ...
- Python之turtle库
在命令行下```python -m pip install turtle``` 大致有两种命令: 运动命令: forward(distance) #向前移动距离distance代表距离 backwar ...
- springboot工程读取配置文件application.yml的写法18045
现在流行springboot框架的项目,里面的默认配置文件为application.yml,我们怎样读取这个配置文件呢? 先贴上我得配置文件吧 目录结构 里面内容 1 写读取配置文件的工具类 @Con ...
- noip第2课作业
1. 大象喝水 [问题描述] 一只大象口渴了,要喝20升水才能解渴,但现在只有一个深h厘米,底面半径为r厘米的小圆桶(h和r都是整数).问大象至少要喝多少桶水才会解渴. 输入:输入有一行,包行两 ...
- Python自动化开发 - Django基础
本节内容 一.什么是web框架 二.MVC和MTV视图 三.Django基本命令 四.路由配置系统 五.编写视图 六.Template 七.ORM 一.什么是web框架 对于所有的web应用,本质上其 ...
- [javascript]Three parts of javascript code snippet
<script> (function(){ /* if (navigator.userAgent.toLowerCase().indexOf("iphone") == ...