FTW - Linux手册页
Linux程序员手册 第3部分
更新日期: 2020-06-09
名称
ftw,nftw-文件树浏览
语法
#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); #include <ftw.h> int ftw(const char *dirpath, int (*fn) (const char *fpath, const struct stat *sb, int typeflag), int nopenfd);
glibc的功能测试宏要求(请参阅feature_test_macros(7)):
nftw():_ XOPEN_SOURCE> = 500
说明
nftw()遍历位于目录dirpath下的目录树,并对树中的每个条目调用一次fn()。默认情况下,在处理目录和文件和子目录之前对其进行处理(遍历)。
为避免用完所有调用进程的文件描述符,nopenfd指定nftw()同时保持打开状态的最大目录数。当搜索深度超过此深度时,nftw()会变慢,因为必须关闭并重新打开目录。 nftw()对于目录树中的每个级别最多使用一个文件描述符。
对于在树中找到的每个条目,nftw()调用带有四个参数的fn():fpath,sb,typeflag和ftwbuf。 fpath是条目的路径名,如果dirpath表示为相对路径名,则表示为相对于调用进程当前工作目录的路径名,如果dirpath表示为相对路径名,则表示为绝对路径名。 dirpath表示为绝对路径名。 sb是指向fpath的stat(2)调用返回的stat结构的指针。
传递给fn()的typeflag参数是一个整数,具有以下值之一:
- FTW_F
- fpath是常规文件。
- FTW_D
- fpath是一个目录。
- FTW_DNR
- fpath是无法读取的目录。
- FTW_DP
- fpath是一个目录,并且在标志中指定了FTW_DEPTH。 (如果未在标志中指定FTW_DEPTH,则将始终在typeflag设置为FTW_D的情况下访问目录。)fpath中的所有文件和子目录均已处理。
- FTW_NS
- 在不是符号链接的fpath上,stat(2)调用失败。造成这种情况的可能原因是,调用方对父目录具有读取权限,因此可以看到文件名fpath,但没有执行权限,因此stat(2)无法访问该文件。 sb指向的缓冲区的内容未定义。
- FTW_SL
- fpath是一个符号链接,并且在标志中设置了FTW_PHYS。
- FTW_SLN
- fpath是指向不存在的文件的符号链接。 (这仅在未设置FTW_PHYS时发生。)在这种情况下,传递给fn()的sb参数包含通过在"悬挂"符号链接上执行lstat(2)返回的信息。 (但请参阅错误。)
nftw()在调用fn()时提供的第四个参数(ftwbuf)是指向FTW类型的结构的指针:
struct FTW { int base; int level; };
base是文件名(即basename组件)在fpath中指定的路径名中的偏移量。 level是目录树中fpath的深度,相对于目录树的根(dirpath,深度为0)。
为了停止树行走,fn()返回一个非零值;该值将成为nftw()的返回值。只要fn()返回0,nftw()就会继续运行,直到遍历整个树为止(在这种情况下它将返回零),或者直到遇到错误(例如malloc(3)失败)为止。情况下将返回-1。
因为nftw()使用动态数据结构,所以退出树遍历的唯一安全方法是从fn()返回非零值。为了允许信号终止遍历而不会导致内存泄漏,请让处理程序设置一个由fn()检查的全局标志。除非程序要终止,否则不要使用longjmp(3)。
nftw()的flags参数是通过对以下零个或多个标志进行"或"运算而形成的:
- FTW_ACTIONRETVAL(since glibc 2.3.3)
- If this glibc-specific flag is set, then
nftw()
handles the return value from
fn()differently.
fn()should return one of the following values:
- FTW_CONTINUE
- 指示nftw()正常继续。
- FTW_SKIP_SIBLINGS
- 如果fn()返回此值,则将跳过当前条目的同级项,并继续在父级中进行处理。
- FTW_SKIP_SUBTREE
- 如果使用目录条目(类型标记为FTW_D)调用fn(),则此返回值将防止将该目录中的对象作为参数传递给fn()。 nftw()继续处理目录的下一个同级对象。
- FTW_STOP
- 使nftw()立即返回返回值FTW_STOP。
其他返回值可能与将来的新操作相关; fn()不应返回上述值以外的值。
为了从中获取FTW_ACTIONRETVAL的定义,必须定义功能测试宏_GNU_SOURCE(在包括任何头文件之前)。
- FTW_CHDIR
- 如果已设置,请在处理每个目录的内容之前对每个目录执行chdir(2)。如果程序需要在fpath所在的目录中执行某些操作,这将很有用。 (指定此标志对在fn的fpath参数中传递的路径名无效。)
- FTW_DEPTH
- 如果已设置,请执行后遍历,即在处理目录及其子目录的内容之后,对目录本身调用fn()。 (默认情况下,每个目录都在其内容之前处理。)
- FTW_MOUNT
- 如果已设置,请保留在同一文件系统中(即,不要越过装入点)。
- FTW_PHYS
- 如果已设置,请勿遵循符号链接。 (这就是您想要的。)如果未设置,将遵循符号链接,但不会报告两次文件。
- 如果未设置FTW_PHYS,但设置了FTW_DEPTH,则永远不会为将作为其后代的目录调用函数fn()。
ftw()
ftw()是较旧的函数,提供nftw()的功能的子集。显着差异如下:
- *
- ftw()没有标志参数。它的行为与使用指定为零的标志调用nftw()时的行为相同。
- *
- 回调函数fn()没有提供第四个参数。
- *
- 通过提供给fn()的typeflag参数传递的值范围较小:仅FTW_F,FTW_D,FTW_DNR,FTW_NS和(可能)FTW_SL。
返回值
这些函数成功返回0,如果发生错误则返回-1。
如果fn()返回非零,则树遍历终止,并且fn()返回的值作为ftw()或nftw()的结果返回。
如果使用FTW_ACTIONRETVAL标志调用nftw(),则fn()用来终止树遍历的唯一非零值是FTW_STOP,并且该值作为nftw()的结果返回。
版本
从2.1版开始,nlibw()在glibc下可用。
属性
有关本节中使用的术语的说明,请参见attribute(7)。
Interface | Attribute | Value |
nftw() | Thread safety | MT-Safe cwd |
ftw() | Thread safety | MT-Safe |
遵循规范
POSIX.1-2001,POSIX.1-2008,SVr4,SUSv1。 POSIX.1-2008将ftw()标记为过时。
备注
POSIX.1-2008注意,如果fn不保留当前工作目录,则结果未指定。
在SUSv1中引入了函数nftw()以及在ftw()中使用FTW_SL。
在某些实现中(例如glibc),ftw()永远不会使用FTW_SL,在其他系统上,FTW_SL仅出现在不指向现有文件的符号链接上,并且在其他系统上,ftw()还将对每个符号链接使用FTW_SL 。如果fpath是符号链接,并且stat(2)失败,则POSIX.1-2008声明是否在typeflag中传递FTW_NS或FTW_SL都未定义。为了获得可预期的结果,请使用nftw()。
BUGS
根据POSIX.1-2008,当传递给fn()的typeflag参数包含FTW_SLN时,由sb指向的缓冲区应包含有关悬挂符号链接的信息(通过在链接上调用lstat(2)获得)。在这一点上,早期的glibc版本正确地遵循了POSIX规范。但是,由于glibc 2.4中引入了回归,当在typeflag中传递FTW_SLN时,由sb指向的缓冲区的内容未定义。 (更确切地说,在这种情况下,缓冲区的内容保持不变。)此回归最终在glibc 2.30中得以修复,因此glibc实现(一次又一次)遵循POSIX规范。
示例
以下程序在其第一个命令行参数中命名的路径下遍历目录树,或者在没有提供参数的情况下遍历当前目录下的目录树。它显示有关每个文件的各种信息。第二个命令行参数可用于指定调用nftw()时控制分配给flags参数的值的字符。
Program source
#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\n", 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], aqdaq) != NULL) flags |= FTW_DEPTH; if (argc > 2 && strchr(argv[2], aqpaq) != NULL) flags |= FTW_PHYS; if (nftw((argc < 2) ? "." : argv[1], display_info, 20, flags) == -1) { perror("nftw"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。