Linux 文件处理 之扫描目录 DIR

本文深入讲解了Linux系统中目录扫描的基本原理与实现方法,涵盖了opendir、readdir、closedir等关键函数的使用,以及如何通过示例程序展示目录结构的遍历过程。
§3.8  扫描目录

Linux系统上一个常见问题就是对目录进行扫描,也就是确定一个特定目录下存放的文件。在shell程序设计中,这很容易做到——只需让shell做一次表达式的通配符扩展。过去,UNIX操作系统的各种变体都允许用户通过编程访问底层文件系统结构。我们仍然可以把目录当作一个普通文件那样打开,并直接读取目录数据项,但不同的文件系统结构及其实现方法已经使这种办法没什么可移植性了。现在,一整套标准的库函数已经被开发出来,使得目录的扫描工作变得简单多了。

与目录操作有关的函数在dirent.h头文件中声明。它们把一个名为DIR的结构作为目录操作的基础。被称为“目录流”的指向这个结构的指针(DIR *)被用来完成各种目录操作,其使用方法与文件流(FILE *)非常相似。目录数据项本身在dirent结构中返回,该结构也是在dirent.h头文件里声明的,用户绝不要直接改动DIR结构中的数据字段。

我们将介绍下面这几个函数:

? opendirclosedir

? readdir

? telldir

? seekdir

 

 

     opendir 函数

opendir函数的作用是打开一个目录并建立一个目录流。如果成功,它返回一个指向DIR结构的指针,该指针用于读取目录数据项。

#include <sys/types.h>

#include <dirent.h>

DIR *opendir(const char *name);

opendir在失败时会返回一个空指针。注意,目录流用一个底层文件描述符来访问目录本身,所以如果打开的文件过多,opendir可能会失败。

 

     readdir 函数

readdir函数将返回一个指针,指针指向的结构里保存着目录流drip中下一个目录项的有关资料。后续的readdir调用将返回后续的目录项。如果发生错误或者到达目录尾,readdir将返回NULLPOSIX兼容的系统在到达目录尾时会返回NULL,但并不改变errno的值,在发生错误时才会设置errno

#include <sys/types.h>

#include <dirent.h>

struct dirent *readdir(DIR *dirp);

注意,如果在readdir函数扫描目录的同时还有其他进程在该目录里创建或删除文件,readdir将不保证能够列出该目录里的所有文件(和子目录)。

dirent结构中包含的目录数据项内容包括以下部分:

? ino_t d_ino——文件的inode节点号。

? char d_name[]——文件的名字。

要想进一步了解目录中某个文件的详细资料,则需要使用在本章前面介绍过的stat调用。

 

     telldir 函数

 

telldir函数的返回值记录着一个目录流里的当前位置。你可以在随后的seekdir调用中利用这个值来重置目录扫描到当前位置。

#include <sys/types.h>

#include <dirent.h>

long int telldir(DIR *dirp);

 

     seekdir 函数

 

seekdir函数的作用是设置目录流dirp的目录项指针。loc的值用来设置指针位置,它应该通过前一个telldir调用获得。

#include <sys/types.h>

#include <dirent.h>

void seekdir(DIR *dirp, long int loc);

     closedir 函数

closedir函数关闭一个目录流并释放与之关联的资源。它在执行成功时返同0,发生错误时返回-1

#include <sys/types.h>

#include <dirent.h>

int closedir(DIR *dirp);

 

在下面的printdir.c程序中,我们把许多文件处理函数集中在一起实现一个简单的目录列表功能。目录中的每个文件单独列在一行上。每个子目录会在它的名字后面加上一个斜线字符/,子目录中的文件在缩进四个空格后依次排列。

程序会逐个切换到每个下级子目录里,这样使它找到的文件都有一个可用的名字,也就是说,它们都可以被直接传递到opendir函数里去。如果目录的嵌套结构太深,程序执行就会失败,因为对允许打开的目录流数目是有限制的。

我们当然可以采取一个更通用的做法,让程序能够通过一个命令行参数来指定起点(从哪个目录开始)。请查阅有关工具程序(如lsfind)的Linux源代码来找到实现更通用程序的方法。

实验:一个目录扫描程序

 

# cat printdir.c

/*  We start with the appropriate headers and then a function, printdir,

    which prints out the current directory.

    It will recurse for subdirectories, using the depth parameter is used for indentation. */

 

#include <unistd.h>

#include <stdio.h>

#include <dirent.h>

#include <string.h>

#include <sys/stat.h>

#include <stdlib.h>

 

void printdir(char *dir, int depth)

{

    DIR *dp;

    struct dirent *entry;

    struct stat statbuf;

 

    if((dp = opendir(dir)) == NULL) {

        fprintf(stderr,"cannot open directory: %s\n", dir);

        return;

    }

    chdir(dir);

    while((entry = readdir(dp)) != NULL) {

        lstat(entry->d_name,&statbuf);

        if(S_ISDIR(statbuf.st_mode)) {

            /* Found a directory, but ignore . and .. */

            if(strcmp(".",entry->d_name) == 0 ||

                strcmp("..",entry->d_name) == 0)

                continue;

            printf("%*s%s/\n",depth,"",entry->d_name);

            /* Recurse at a new indent level */

            printdir(entry->d_name,depth+4);

        }

        else printf("%*s%s\n",depth,"",entry->d_name);

    }

    chdir("..");

    closedir(dp);

}

 

/*  Now we move onto the main function.  */

 

int main()

{

    printf("Directory scan of /home:\n");

    printdir("/home",0);

    printf("done.\n");

 

    exit(0);

}

 

 

cat printdir2.c  

/*  We start with the appropriate headers and then a function, printdir,

    which prints out the current directory.

    It will recurse for subdirectories, using the depth parameter is used for indentation. */

 

#include <unistd.h>

#include <stdio.h>

#include <dirent.h>

#include <string.h>

#include <sys/stat.h>

#include <stdlib.h>

 

void printdir(char *dir, int depth)

{

    DIR *dp;

    struct dirent *entry;

    struct stat statbuf;

 

    if((dp = opendir(dir)) == NULL) {

        fprintf(stderr,"cannot open directory: %s\n", dir);

        return;

    }

    chdir(dir);

    while((entry = readdir(dp)) != NULL) {

        lstat(entry->d_name,&statbuf);

        if(S_ISDIR(statbuf.st_mode)) {

            /* Found a directory, but ignore . and .. */

            if(strcmp(".",entry->d_name) == 0 ||

                strcmp("..",entry->d_name) == 0)

                continue;

            printf("%*s%s/\n",depth,"",entry->d_name);

            /* Recurse at a new indent level */

            printdir(entry->d_name,depth+4);

        }

        else printf("%*s%s\n",depth,"",entry->d_name);

    }

    chdir("..");

    closedir(dp);

}

 

/*  Now we move onto the main function.  */

 

int main(int argc, char* argv[])

{

    char *topdir, pwd[2]=".";

    if (argc != 2)

        topdir=pwd;

    else

        topdir=argv[1];

 

    printf("Directory scan of %s\n",topdir);

    printdir(topdir,0);

    printf("done.\n");

 

    exit(0);

}

### DLP扫描处理文件存储目录配置路径 DLP(Data Loss Prevention,数据防泄漏)系统的功能之一是对敏感数据进行扫描并防止其泄露。在实际部署过程中,通常会有一个专门的存储目录用于存放等待扫描文件。此目录的具体位置取决于所使用的具体DLP解决方案以及管理员的配置。 一般情况下,DLP软件会在安装时提供默认的存储路径设置选项,这些路径可能位于操作系统标准的临时文件夹或指定的应用程序数据区域中。例如,在Windows环境中,默认路径可能是类似于`C:\ProgramData\<VendorName>\<ProductName>\PendingFiles`这样的结构[^1]。而在Linux环境下,则可能会使用如`/var/opt/<vendor-name>/<product-name>/pending_files`之类的路径[^2]。 对于具体的DLP产品而言,要找到确切的“待处理文件”的存储目录,可以通过查阅该产品的官方文档来获取更精确的信息。如果无法直接访问文档或者需要快速定位当前环境中的实际路径,还可以尝试以下几种方法: #### 方法一:查看管理界面配置 许多现代化的企业级DLP工具都提供了图形化的用户界面(UI),允许管理员轻松调整各项参数设定,其中包括上传至系统准备接受进一步审查之前暂时保存下来的那些资料所在的物理地址。登录到相应的Web门户或者其他类型的管理中心后寻找有关输入队列(Input Queue)部分即可发现相关联条目指向的确切地方[^3]。 #### 方法二:检查日志记录 大多数企业版应用程序都会生成详细的运行状况报告连同错误消息一起存入特定的日志文件里以便后续排查问题之需。因此也可以通过审阅这些日记内容去追踪哪些磁盘分区被用来作为缓冲区用途。比如利用grep命令搜索关键词"pending" 或者 "queue" 来缩小范围从而更快锁定目标所在之处。 ```bash grep -ri 'pending\|queue' /path/to/logs/ ``` 以上脚本将会递归地在整个给定的日志根目录及其子文件夹下查找含有预设关键字的所有匹配项,并显示它们的位置和上下文信息。 #### 方法三:咨询供应商技术支持团队 当内部探索手段均未果之时,联系原厂的技术支持人员不失为一种明智之举。他们往往能够基于丰富的经验迅速解答疑惑并向用户提供额外的帮助资源链接等附加价值服务项目。 --- ### 示例代码片段展示如何动态修改某些开源项目的相应变量值(仅作参考) 下面给出了一段虚构的例子说明假如我们正在维护一个名为MyCustomDLPSolution 的Python库的话,那么就可以按照如下方式实现对其内部属性my_pending_dir 进行动态赋新值得目的: ```python from my_custom_dlp_solution import MyConfigManager config_manager = MyConfigManager() new_path = "/mnt/new_storage/pending" if config_manager.set_pending_directory(new_path): print(f"DLP pending directory successfully updated to {new_path}.") else: print("Failed to update the DLP pending directory.") ``` 请注意这只是一个示意性的例子而已,真实世界里的做法应当严格遵循各个不同品牌型号设备手册上的指导方针来进行操作以免造成不必要的损害事故! ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值