fts函数用法详解
fts函数简介
- 头文件包含
#include <sys/types.h>
#include <sys/stat.h>
#include <fts.h>
- 函数定义
FTS *fts_open(char * const * path_argv , int options ,
int (* compar )(const FTSENT **, const FTSENT **));
FTSENT *fts_read(FTS * ftsp );
FTSENT *fts_children(FTS * ftsp , int instr );
int fts_set(FTS * ftsp , FTSENT * f , int instr );
int fts_close(FTS * ftsp );
fts函数常见使用错误
- 编译错误
warning: implicit declaration of function ‘fts’ [-Wimplicit-function-declaration]
解决办法:包含头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fts.h>
fts函数详细描述
fts函数用于遍历文件层次结构。简单的概述是,fts_open ()函数返回一个“句柄”(类型为"FTS\ *" ),指文件层次结构“流”。然后该句柄被提供给其他fts函数。函数fts_read ()返回一个指向描述文件层次结构中的一个文件的结构的指针。函数fts_children ()返回指向结构链表的指针,每个结构描述层次结构中的目录中包含的一个文件。
一般情况下,访问目录的时间可以区分为两次;在前序(在他们的任何后代被访问之前)和后序(在他们的所有后代都被访问之后)。文件访问一次。可以“逻辑地”遍历层次结构(访问符号链接指向的文件)或物理地遍历层次结构(访问符号链接本身),命令遍历层次结构或修剪和/或重新遍历层次结构的部分。
包含文件
FTSENT结构包含描述文件的字段。该结构至少包含以下字段(还有其他字段应该被认为对实现是私有的):
typedef struct _ftsent {
unsigned short fts_info; /* flags for FTSENT structure */
char *fts_accpath; /* access path */
char *fts_path; /* root path */
short fts_pathlen; /* strlen(fts_path) +
strlen(fts_name) */
char *fts_name; /* filename */
short fts_namelen; /* strlen(fts_name) */
short fts_level; /* depth (\-1 to N) */
int fts_errno; /* file errno */
long fts_number; /* local numeric value */
void *fts_pointer; /* local address value */
struct _ftsent *fts_parent; /* parent directory */
struct _ftsent *fts_link; /* next file structure */
struct _ftsent *fts_cycle; /* cycle structure */
struct stat *fts_statp; /* stat(2) information */
} FTSENT;
这些字段定义如下:
- fts_info描述返回的FTSENT结构及其表示的文件的下列值之一。除了没有错误的目录( FTS_D )之外,所有这些条目都是终端的,也就是说,它们不会被重新访问,也不会访问它们的任何后代。.RS
- FTS_D按预定顺序访问的目录。
- FTS_DC在树中引起循环的目录。(FTSENT结构的fts_cycle字段也将被填入。)
- FTS_DEFAULT表示其他fts_info值之一未显式描述的文件类型的任何FTSENT结构。
- FTS_DNR无法读取的目录。这是一个错误返回,fts_errno字段将被设置为指示是什么导致了错误。
- FTS_DOT一个名为“.”的文件。或者“..”它没有被指定为fts_open ()的文件名(请参见FTS_SEEDOT )
- FTS_DP按后序访问的目录。FTSENT结构的内容将从按预定顺序返回时起保持不变,即fts_info字段设置为FTS_D
- FTS_ERR这是一个错误返回,fts_errno字段将被设置为指示导致错误的原因。
- FTS_F一个常规文件。
- FTS_NS一个没有stat (2)信息可用的文件。fts_statp字段的内容未定义。这是一个错误返回,fts_errno字段将被设置为指示是什么导致了错误。
- FTS_NSOK一个没有请求stat (2)信息的文件。fts_statp字段的内容未定义。
- 一个符号链接。
- 目标不存在的符号链接。fts_statp字段的内容引用符号链接本身的文件特征信息。.Re
- fts_accpath从当前目录访问文件的路径。
- fts_path文件相对于遍历根目录的路径。此路径包含指定给fts_open ()作为前缀的路径。
- fts_pathlen由fts_path和fts_name 引用的字符串长度之和
- fts_name文件的名称。
- fts_namelen fts_name 引用的字符串的长度
- fts_level遍历的深度,编号从-1到N,在那里找到这个文件。表示遍历的起点(或根)的父级的FTSENT结构编号为-1,根本身的FTSENT结构编号为0。
- 如果fts_children ()或fts_read ()返回一个FTSENT结构,其fts_info字段设置为FTS_DNR 、FTS_ERR 或FTS_NS ,则fts_errno字段包含指定错误原因的错误号(即errno值)。否则,fts_errno字段的内容是未定义的。
- fts_number此字段提供给应用程序使用,并且不被fts函数修改。它被初始化为0。
- fts_pointer此字段提供给应用程序使用,并且不被fts函数修改。它被初始化为NULL。
- fts_parent指向FTSENT结构的指针,该结构引用紧靠当前文件上方的层次结构中的文件,即该文件所在的目录。还提供了初始入口点的父结构,但是,只保证初始化fts_level 、fts_number 和fts_pointer字段。
- fts_link从fts_children ()函数返回后,fts_link字段指向以空终止的目录成员链表中的下一个结构。否则,fts_link字段的内容是未定义的。
- fts_cycle如果一个目录导致层次结构中的循环(请参见FTS_DC ),因为两个目录之间的硬链接或指向目录的符号链接,结构的fts_cycle字段将指向层次结构中的FTSENT结构,该结构引用与当前FTSENT结构相同的文件。否则,fts_cycle字段的内容未定义。
- fts_statp指向文件的stat (2)信息的指针。
单个缓冲区用于文件层次结构中所有文件的所有路径。因此,fts_path和fts_accpath字段被保证为null终止的only,因为fts_read ()最近返回的文件要使用这些字段引用其他FTSENT结构表示的任何文件,就需要使用该FTSENT结构的fts_pathlen字段中包含的信息修改路径缓冲区。在尝试进一步调用fts_read ()之前,应撤消任何此类修改。fts_name字段始终以空结尾。fts_open() fts_accpath0函数获取一个指向字符指针数组的指针,该数组命名一个或多个路径,这些路径构成要遍历的逻辑文件层次结构。数组必须由空指针终止。
有许多选项,其中至少有一个(必须指定FTS_LOGICAL或FTS_PHYSICAL )。这些选项是通过ORing以下值选择的:
- FTS_COMFOLLOW无论是否还指定了FTS_LOGICAL,此选项都会立即跟踪指定为根路径的任何符号链接。
- FTS_LOGICAL此选项导致fts例程返回符号链接目标的FTSENT结构,而不是符号链接本身。如果设置了此选项,则将FTSENT结构返回到应用程序的唯一符号链接是那些引用不存在文件的链接。FTS_LOGICAL或FTS_PHYSICAL must提供给fts_open ()函数。
- FTS_NOCHDIR作为一种性能优化,fts函数在文件层次结构中遍历时会更改目录。这样做的副作用是,在遍历过程中,应用程序不能依赖于位于任何特定目录中。FTS_NOCHDIR选项关闭此优化,fts函数不会更改当前目录。请注意,除非指定了FTS_NOCHDIR,并且提供了绝对路径名作为fts_open ()的参数,否则应用程序本身不应更改其当前目录并尝试访问文件
- FTS_NOSTAT默认情况下,返回的FTSENT结构为每个访问的文件引用文件特征信息(statp字段)。作为性能优化,此选项放宽了这一要求,允许fts函数将fts_info字段设置为FTS_NSOK,并保留statp字段的内容不定义。
- FTS_PHYSICAL此选项导致fts例程返回符号链接本身的FTSENT结构,而不是它们指向的目标文件。如果设置了此选项,则层次结构中所有符号链接的FTSENT结构将返回给应用程序。FTS_LOGICAL或FTS_PHYSICAL must提供给fts_open ()函数。
- FTS_SEEDOT默认情况下,除非它们被指定为fts_open ()的任何名为“.”的文件的路径参数。或者“..”在文件层次结构中遇到的。此选项导致fts例程为它们返回FTSENT结构。
- FTS_XDEV此选项防止fts下降到具有不同于开始下降的文件的设备号的目录中。
参数compar ()指定一个用户定义的函数,该函数可用于对层次结构的遍历进行排序。它将两个指向FTSENT结构指针的指针作为参数,并应返回负值、零或正值,以指示第一个参数引用的文件是否在第二个参数引用的文件之前、相对于第二个参数引用的文件之前或之后。FTSENT结构的fts_accpath 、fts_path 和fts_pathlen字段可以在此比较中使用never。如果fts_info字段设置为FTS_NS或FTS_NSOK ,fts_statp字段也不能设置为PPPP8或FTS_NSOK 。如果compar ()参数为NULL,则目录遍历顺序为path_argv中列出的根路径的顺序,以及目录中列出的所有其他路径的顺序。fts_read() fts_read ()函数返回一个指向描述层次结构中文件的FTSENT结构的指针。目录(可读且不会引起循环)至少被访问两次,一次按预定顺序,一次按预定顺序。所有其他文件至少被访问一次。(不导致循环的目录之间的硬链接或符号链接到符号链接可能导致文件被访问不止一次,或目录被访问不止两次。)
如果层次结构的所有成员都已返回,fts_read ()返回NULL并将外部变量errno设置为0。如果发生与层次结构中的文件无关的错误,fts_read ()返回NULL并适当设置errno。如果发生与返回的文件相关的错误,则返回指向FTSENT结构的指针,并且可以设置errno,也可以没有设置PPPP5(请参见fts_info )
fts_read ()返回的FTSENT结构可以在调用相同文件层次流上的fts_close ()之后被覆盖,或者在调用相同文件层次流上的fts_read ()之后被覆盖,除非它们表示目录类型的文件,在这种情况下,它们将不会被覆盖,直到调用fts_read ()之后,函数fts_read ()在后序中返回了FTSENT结构。fts_children() fts_children ()函数返回一个指向FTSENT结构的指针,该结构描述由fts_read ()0结构表示的目录中的文件的以空结尾的链表中的第一个条目,最近由fts_read ()返回。该列表通过FTSENT结构的fts_link字段链接,并且根据用户指定的比较函数(如果有的话)进行排序。重复调用fts_children ()将重新创建此链表。
作为一个特例,如果fts_read ()尚未调用层次结构,则fts_children ()将返回一个指针,指向指定给fts_open ()的逻辑目录中的文件,即指定给fts_open ()的参数;否则,如果fts_read ()最近返回的FTSENT结构不是按预定顺序访问的目录,或者该目录不包含任何文件,则fts_children ()返回NULL并将errno设置为零。如果发生错误,fts_children ()返回NULL并适当设置errno。
在调用相同文件层次结构流上的fts_children ()、fts_close ()或fts_read ()之后,fts_children ()返回的FTSENT结构可能会被覆盖。
instr参数要么为零,要么为以下值:
- FTS_NAMEONLY只需要文件的名称。返回的结构链表中的所有字段的内容都是未定义的,但fts_name和fts_namelen字段除外。fts_set()函数fts_set ()允许用户应用程序确定流ftsp 的文件f的进一步处理。fts_set ()函数在成功时返回0,如果发生错误则返回-1。
instr参数要么是0(意思是“什么都不做”),要么是以下值之一:
- FTS_AGAIN重新访问文件;任何文件类型都可以重新访问。对fts_read ()的下一次调用将返回所引用的文件。届时结构的fts_stat和fts_info字段将被重新初始化,但不会更改其他字段。此选项仅对最近从fts_read ()返回的文件有意义。通常用于后序目录访问,在后序目录访问中,它会导致重新访问该目录(preorder和postorder)及其所有后代。
- FTS_FOLLOW引用的文件必须是符号链接。如果引用的文件是fts_read ()最近返回的文件,则下一次调用fts_read ()将返回该文件,其中fts_info和fts_statp字段重新初始化,以反映符号链接的目标,而不是符号链接本身。如果文件是fts_children ()最近返回的文件之一,则结构的fts_info和fts_statp字段在fts_read ()返回时将反映符号链接的目标,而不是符号链接本身。在这两种情况下,如果符号链接的目标不存在,则返回的结构的字段将保持不变,fts_info字段将设置为fts_read ()0.ip。如果链接的目标是一个目录,则完成preorder返回,然后返回其所有后代,然后再返回postorder返回。
- FTS_SKIP没有访问此文件的后代。该文件可能是fts_children ()或fts_read ()最近返回的文件之一fts_close()。fts_close ()函数关闭ftsp引用的文件层次结构流,并将当前目录恢复到调用fts_open ()以打开ftsp 的目录。fts_close ()函数在成功时返回0,如果发生错误,返回-1。
fts函数错误码
函数fts_open ()可能失败,并为open (2)和malloc (3)指定的任何错误设置errno
函数fts_close ()可能失败,并为chdir (2)和close (2)指定的任何错误设置errno
函数fts_read ()和fts_children ()可能会失败,并针对为chdir (2) malloc (3) opendir (3) readdir (3)和stat (2)指定的任何错误设置errno
此外,fts_children ()、fts_open ()和fts_set ()可能会失败,并设置errno如下:
- EINVAL 、options或instr无效。
评论区