FTW - Linux手册页

时间:2019-08-20 18:00:56  来源:igfitidea点击:

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():fpathsb,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_FFTW_DFTW_DNR,FTW_NS和(可能)FTW_SL。

返回值

这些函数成功返回0,如果发生错误则返回-1。

如果fn()返回非零,则树遍历终止,并且fn()返回的值作为ftw()或nftw()的结果返回。

如果使用FTW_ACTIONRETVAL标志调用nftw(),则fn()用来终止树遍历的唯一非零值是FTW_STOP,并且该值作为nftw()的结果返回。

版本

从2.1版开始,nlibw()在glibc下可用。

属性

有关本节中使用的术语的说明,请参见attribute(7)。

InterfaceAttributeValue
nftw()Thread safetyMT-Safe cwd
ftw()Thread safetyMT-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);
}

另外参见

stat(2),fts(3),readdir(3)

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/