Linux环境编程文件目录操作之nftw,ftw函数

本篇记录Linux环境下文件树操作的nftw和ftw函数。nftw()可遍历目录树并对每个条目调用fn(),默认按序遍历,nopenfd指定其同时打开的最大目录数。还给出了ntfw和tfw函数文件树遍历的示例及运行结果,并提供了相关参考资料。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇记录在Linux环境下,文件树操作之nftw和tfw函数,说明:
nftw()遍历位于目录目录路径下的目录树,并对树中的每个条目调用fn()一次。默认情况下,目录在其包含的文件和子目录之前进行处理(按序遍历)。 
为了避免用尽调用进程的所有文件描述符,nopenfd指定了nftw()同时打开的最大目录数。当搜索深度超过此值时,nftw()将变慢,因为目录必须关闭并重新打开。nftw)在目录树中的每个级别最多使用一个文件描述符。

首先查看帮助文档:

1.ntfw函数文件树遍历。

函数名nftw
相关函数ftw
表头文件#include <ftw.h>
函数定义

int nftw(const char *dirpath,
             int (*fn) (const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf),
             int nopenfd, int flags);

函数说明

nftw()与ftw()很像,都是从参数dir指定的目录开始, 往下一层层地递归遍历子目录。 每进入一个目录,便会调用参数*fn定义的函数来处理。nftw()会传四个参数给fn(). 第一个参数*file指向当时所在的目录路径,第二个参数是*sb, 为stat结构指针(结构定义请参考stat()),第三个参数为旗标,有底下几种可能值:
FTW_F                         一般文件
FTW_D                         目录
FTW_DNR                      不可读取的目录。此目录以下将不被遍历
FTW_SL                         符号连接
FTW_NS                        无法取得stat结构数据,在可能是权限问题
FTW_DP                        目录,而且子目录都已被遍历过了
FTW_SLN                       符号连接,但连接不存在的文件

fn()的第四个参数是FTW结构,定义如下:

struct  FTW
{
     int  base;
     int  level; //level代表遍历时的深度
}

nftw()第三个参数depth代表nftw()在进行遍历目录时可同时打开的文件数。
ftw()在遍历时每一层目录至少需要一个文件描述词,如果遍历时用完了depth所给予的限制数目,整个遍历将因不断地关文件和开文件操作而显得的缓慢

nftw()最后一个参数flags用来指定遍历时的动作,可指定下列的操作或用OR组合
FTW_CHDIR                 在读目录之前先用chdir()移到此目录
FTW_DEPTH                执行深度优先搜索。在遍历此目录前先将所有子目录遍历完
FTW_MOUNT               遍历时不要跨越到其他文件系统
FTW_PHYS                  不要遍历符号连接的目录。预设会遍历符号连接目录

返回值成功返回0,失败返回-1

示例:

#define _XOPEN_SOURCE 500
#include <iostream>
#include <ftw.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

using namespace std;

static int display_info_nftw(const char *fpath, const struct stat *sb,
                        int tflag, struct FTW *ftwbuf)
{
    printf("%-3s %2d ",
           (tflag == FTW_D) ?   "d"   : (tflag == FTW_DNR) ? "dnr" :
           (tflag == FTW_DP) ?  "dp"  : (tflag == FTW_F) ?   "f" :
           (tflag == FTW_NS) ?  "ns"  : (tflag == FTW_SL) ?  "sl" :
           (tflag == FTW_SLN) ? "sln" : "???",
           ftwbuf->level);

    if (tflag == FTW_NS)
        printf("-------");
    else
        printf("%7jd", (intmax_t) sb->st_size);
    //ftwbut->base base是在fpath中给定的路径名中的文件名(basename)的偏移量
    //如果不加路径偏移里,就会显示全路径名,与下面一行打印可以看出对比
    printf("\t%-40s\t%d\t%s\n", fpath, ftwbuf->base, fpath + ftwbuf->base);
    //printf("\t%-40s\t%d\t%s\n", fpath, ftwbuf->base, fpath);

    return 0;           /* To tell nftw() to continue */
}

int main()
{
    int flags = 0;
    char path[] = "/home/scott/Videos/mp4/";//这个是base的长度值 23
    int len = strlen(path);
    printf("len=======================%d\n", len);
    flags |= FTW_DEPTH;
    //flags |= FTW_PHYS;

    if (nftw(path, display_info_nftw, 20, flags) == -1) {
        perror("nftw");
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}

运行结果:

2.tfw函数文件树遍历。

函数名ftw
相关函数nftw
表头文件#include <ftw.h>
函数定义

int ftw(const char *dirpath,
          int (*fn) (const char *fpath, const struct stat *sb, int typeflag),
          int nopenfd);

函数说明

ftw() 是一个旧函数,它提供的功能是nftw()函数功能的一个子集。它们的区别如下:

ftw() 没有flags参数。它和调用参数flags 为0的nftw()等价对于在树中发现的每个节点,ftw() 为其调用带3个参数的函数fn(),这3个参数为fpathsbtypeflagfpath是节点的路径名,它可以表示为相对路径或者绝对路径,相对路径是相对调用进程的当前工作目录。sb是为fpath调用stat函数所返回的指向stat结构体的指针。提供给fn()typeflag 参数可供选择的范围更小:只有取下面其中一个值:

  • FTW_F fpath是一个普通文件。
  • FTW_D fpath是一个目录。
  • FTW_DNR fpath是一个不能被读的目录。
  • FTW_DP fpath是一个目录,并且 flag参数被指定为FTW_DEPTH。(如果flags没有被指定为FTW_DEPTH,那么访问目录时使用的typeflag总会是FTW_D。)路径fpath下的所有文件和子目录已经被处理过了。
  • FTW_NS 在不是符号链接的fpath上调用stat失败。可能的原因是调用者对父目录有读权限,所以文件名fpath可以被看到,但是没有执行权限,所以执行stat失败。由sb指向的缓存的内容是未定义的。
  • FTW_SL fpath是一个符号链接,flags被设置为FTW_PHYS
返回值成功返回0,失败返回-1

示例:

#define _XOPEN_SOURCE 500
#include <iostream>
#include <ftw.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

using namespace std;

static int display_info_ftw(const char *fpath, const struct stat *sb, int tflag)
{
    printf("%-3s\t",
           (tflag == FTW_D) ?   "d"   : (tflag == FTW_DNR) ? "dnr" :
           (tflag == FTW_DP) ?  "dp"  : (tflag == FTW_F) ?   "f" :
           (tflag == FTW_NS) ?  "ns"  : (tflag == FTW_SL) ?  "sl" :
           (tflag == FTW_SLN) ? "sln" : "???");

    if (tflag == FTW_NS)
        printf("-------");
    else
        printf("%7jd", (intmax_t) sb->st_size);
    printf("\t%-40s\tuid=%d\tgid=%d\n", fpath, sb->st_uid, sb->st_gid);

    return 0;           /* To tell nftw() to continue */
}

int main()
{
    char path[] = "/home/scott/Videos/photo";
    //int len = strlen(path);
    //printf("len=======================%d\n", len);
    if (ftw(path, display_info_ftw, 20) == -1) {
        perror("ftw");
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}


运行结果:

参考:

c库函数 nftw详解_嘿咻嘿咻_新浪博客

https://www.ibm.com/docs/zh/zos/3.1.0?topic=functions-nftw-nftw64-traverse-file-tree

APUE-文件和目录(六)函数ftw和nftw - HarlanC - 博客园

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值