ftw函数用法详解
ftw函数简介
- 头文件包含
#include <ftw.h>
#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 );
int ftw(const char * dirpath ,
int (* fn ) (const char * fpath , const struct stat * sb ,
int typeflag ),
int nopenfd );
ftw函数常见使用错误
- 编译错误
warning: implicit declaration of function ‘ftw’ [-Wimplicit-function-declaration]
解决办法:包含头文件
#include <ftw.h>
#include <ftw.h>
ftw函数详细描述
nftw ()遍历位于目录dirpath下的目录树,并对树中的每个条目调用一次fn()。默认情况下,在目录包含的文件和子目录之前处理目录(预序遍历)。
为了避免用完调用进程的所有文件描述符,nopenfd指定nftw ()同时打开的最大目录数。当搜索深度超过这个时,nftw ()将变得更慢,因为目录必须关闭和重新打开。nftw ()对目录树中的每个级别最多使用一个文件描述符。
对于在树中找到的每个条目,nftw ()用四个参数调用fpath 3():fpath sb typeflag 和ftwbuf fpath是条目的路径名,如果dirpath表示为相对路径名,则表示为在调用nftw ()时相对于调用进程当前工作目录的路径名;如果dirpath表示为绝对路径名,则表示为绝对路径名。sb是对fpath 调用stat (2)返回的stat结构的指针
传递给fn ()的typeflag参数是一个整数,它具有以下值之一:
- FTW_F fpath是一个常规文件。
- FTW_D fpath是一个目录。
- FTW_DNR fpath是一个不能读取的目录。
- FTW_DP fpath是一个目录,FTW_DEPTH是在pflags中指定的。(如果flags 中没有指定 FTW_DEPTH ,那么将始终访问目录,将typeflag设置为FTW_D ),所有fpath中的文件和子目录都已处理。
- FTW_NS 在不是符号链接的fpath 上的stat (2)调用失败。可能的原因是调用方对父目录具有读取权限,因此可以看到文件名fpath,但没有执行权限,因此无法访问stat (2)。sb指向的缓冲区内容未定义。
- FTW_SL fpath是符号链接,FTW_PHYS是在pflags中设置的。
- FTW_SLN fpath是指向不存在文件的符号链接。(只有在未设置FTW_PHYS的情况下才会发生这种情况。)在本例中,传递给fn ()的sb参数包含通过对“悬空”符号链接执行lstat (2)而返回的信息。(但请参阅bugs。)
nftw ()在调用fn()时提供的第四个参数。ri(ftwbuf)是指向pFTW类型结构的指针:
struct FTW {
int base;
int level;
};
base是fpath 中给出的路径名中的文件名(即basename组件)的偏移量level是fpath在目录树中相对于树的根的深度。ri(dirpath,其深度为0)。
为了停止树遍历,fn()返回一个非零值;只要PPPP3()返回0,这个值就会变成nftw ()的返回值,nftw ()将继续下去,直到它遍历了整个树,在这种情况下它将返回零,或者直到它遇到错误(如malloc (3)失败),在这种情况下它将返回-1。
因为nftw ()使用动态数据结构,所以退出树遍历的唯一安全方法是从fn()返回一个非零值。为了允许一个信号终止遍历而不会导致内存泄漏,让处理程序设置一个由PPPP2()检查的全局标志。Don't使用longjmp (3),除非程序要终止。
nftw ()的flags参数由以下零个或多个标志组成:
- 如果设置了这个特定于glibc的标志,那么nftw ()将以不同的方式处理来自fn ()的返回值。fn ()应该返回以下值之一:.rs
- FTW_CONTINUE 指示nftw ()正常继续。
- 如果fn()返回此值,则将跳过当前项的兄弟姐妹,并在父项中继续处理。
- 如果fn()被调用的条目是一个目录(typeflag是FTW_D),这个返回值将防止该目录中的对象作为参数传递给PPPP2()。nftw ()继续处理该目录的下一个同级目录。
- FTW_STOP 使nftw ()立即返回,返回值为pFTW_STOP。
其他返回值可以与未来的新操作相关联;fn()不应返回上面列出的值以外的值。
为了从
- 如果设置了 FTW_CHDIR ,则在处理每个目录的内容之前对其执行chdir (2)。如果程序需要在fpath所在的目录中执行某些操作,这将非常有用。(指定此标志对在fn )的fpath参数中传递的路径名没有影响)
- 如果设置了 FTW_DEPTH ,则执行后序遍历,即为目录本身调用fn(),处理目录及其子目录的内容。(默认情况下,每个目录都处理before其内容。)
- 如果设置了 FTW_MOUNT ,则保持在相同的文件系统中(即,不要跨越挂载点)。
- 如果设置了 FTW_PHYS ,则不要遵循符号链接。(这就是你想要的。)如果未设置,则会遵循符号链接,但不会报告两次文件。.ip如果没有设置FTW_PHYS,而是设置了FTW_DEPTH,那么函数fn ()将永远不会被调用给它自己的子代目录。ftw() ftw ()是一个较老的函数,它提供了nftw ()功能的一个子集,显著的区别如下:
- ftw ()没有flags参数。它的行为与调用nftw ()时的行为相同,flags指定为零。
- 回调函数fn ()没有提供第四个参数。
- 通过提供给fn ()的typeflag参数传递的值范围较小:只有FTW_F 、FTW_D 、FTW_DNR 、FTW_NS 和(可能)FTW_SL
ftw函数返回值
这些函数在成功时返回0,在发生错误时返回-1。
如果fn()返回非零,则终止树遍历,并将ppp2()返回的值作为ftw ()或nftw ()的结果返回
如果使用FTW_ACTIONRETVAL标志调用nftw (),那么fn()终止树遍历时应该使用的唯一非零值是FTW_STOP,该值将作为nftw ()的结果返回
ftw函数其他说明
POSIX.1-2008注意到,如果fn不保留当前工作目录,结果是未指定的。
在susv1中介绍了nftw ()函数以及FTW_SL与ftw ()的使用。
在一些实现中(例如,glibc),ftw ()将永远不会使用FTW_SL,在其他系统中,ppp6只用于不指向现有文件的符号链接,在其他系统中,ftw ()将对每个符号链接使用ppp6。如果fpath是一个符号链接,并且stat (2)失败,POSIX.1-2008声明在typeflag 中传递FTW_NS或FTW_SL以获得可预测的结果是未定义的,则使用nftw ()
ftw函数使用举例
下面的程序遍历第一个命令行参数中命名的路径下的目录树,如果没有提供参数,则遍历当前目录下的目录树。它显示关于每个文件的各种信息。第二个命令行参数可用于指定字符,这些字符在调用nftw () Program source时控制分配给flags参数的值&
#define _XOPEN_SOURCE 500
#include <ftw.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
static int
display_info(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);
printf(" %\-40s %d %s\en",
fpath, ftwbuf\->base, fpath + ftwbuf\->base);
return 0; /* To tell nftw() to continue */
}
int
main(int argc, char *argv[])
{
int flags = 0;
if (argc > 2 && strchr(argv[2], \(aqd\(aq) != NULL)
flags |= FTW_DEPTH;
if (argc > 2 && strchr(argv[2], \(aqp\(aq) != NULL)
flags |= FTW_PHYS;
if (nftw((argc < 2) ? "." : argv[1], display_info, 20, flags)
== \-1) {
perror("nftw");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
评论区