1.\" Copyright (c) 1989, 1991, 1993, 1994 2.\" The Regents of the University of California. All rights reserved. 3.\" 4.\" Redistribution and use in source and binary forms, with or without 5.\" modification, are permitted provided that the following conditions 6.\" are met: 7.\" 1. Redistributions of source code must retain the above copyright 8.\" notice, this list of conditions and the following disclaimer. 9.\" 2. Redistributions in binary form must reproduce the above copyright 10.\" notice, this list of conditions and the following disclaimer in the 11.\" documentation and/or other materials provided with the distribution. 12.\" 3. Neither the name of the University nor the names of its contributors 13.\" may be used to endorse or promote products derived from this software 14.\" without specific prior written permission. 15.\" 16.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26.\" SUCH DAMAGE. 27.\" 28.Dd June 30, 2025 29.Dt FTS 3 30.Os 31.Sh NAME 32.Nm fts 33.Nd traverse a file hierarchy 34.Sh LIBRARY 35.Lb libc 36.Sh SYNOPSIS 37.In fts.h 38.Ft FTS * 39.Fn fts_open "char * const *path_argv" "int options" "int (*compar)(const FTSENT * const *, const FTSENT * const *)" 40.Ft FTS * 41.Fn fts_open_b "char * const *path_argv" "int options" "int (^compar)(const FTSENT * const *, const FTSENT * const *)" 42.Ft FTSENT * 43.Fn fts_read "FTS *ftsp" 44.Ft FTSENT * 45.Fn fts_children "FTS *ftsp" "int options" 46.Ft int 47.Fn fts_set "FTS *ftsp" "FTSENT *f" "int options" 48.Ft void 49.Fn fts_set_clientptr "FTS *ftsp" "void *clientdata" 50.Ft void * 51.Fn fts_get_clientptr "FTS *ftsp" 52.Ft FTS * 53.Fn fts_get_stream "FTSENT *f" 54.Ft int 55.Fn fts_close "FTS *ftsp" 56.Sh DESCRIPTION 57The 58.Nm 59functions are provided for traversing 60.Ux 61file hierarchies. 62A simple overview is that the 63.Fn fts_open 64and 65.Fn fts_open_b 66functions return a 67.Dq handle 68on a file hierarchy, which is then supplied to 69the other 70.Nm 71functions. 72The function 73.Fn fts_read 74returns a pointer to a structure describing one of the files in the file 75hierarchy. 76The function 77.Fn fts_children 78returns a pointer to a linked list of structures, each of which describes 79one of the files contained in a directory in the hierarchy. 80In general, directories are visited two distinguishable times; in pre-order 81(before any of their descendants are visited) and in post-order (after all 82of their descendants have been visited). 83Files are visited once. 84It is possible to walk the hierarchy 85.Dq logically 86(ignoring symbolic links) 87or physically (visiting symbolic links), order the walk of the hierarchy or 88prune and/or re-visit portions of the hierarchy. 89.Pp 90Two structures are defined (and typedef'd) in the include file 91.In fts.h . 92The first is 93.Vt FTS , 94the structure that represents the file hierarchy itself. 95The second is 96.Vt FTSENT , 97the structure that represents a file in the file 98hierarchy. 99Normally, an 100.Vt FTSENT 101structure is returned for every file in the file 102hierarchy. 103In this manual page, 104.Dq file 105and 106.Dq Vt FTSENT No structure 107are generally 108interchangeable. 109.Pp 110The 111.Vt FTS 112structure contains space for a single pointer, which may be used to 113store application data or per-hierarchy state. 114The 115.Fn fts_set_clientptr 116and 117.Fn fts_get_clientptr 118functions may be used to set and retrieve this pointer. 119This is likely to be useful only when accessed from the sort 120comparison function, which can determine the original 121.Vt FTS 122stream of its arguments using the 123.Fn fts_get_stream 124function. 125The two 126.Li get 127functions are also available as macros of the same name. 128.Pp 129The 130.Vt FTSENT 131structure contains at least the following fields, which are 132described in greater detail below: 133.Bd -literal 134typedef struct _ftsent { 135 int fts_info; /* status for FTSENT structure */ 136 char *fts_accpath; /* access path */ 137 char *fts_path; /* root path */ 138 size_t fts_pathlen; /* strlen(fts_path) */ 139 char *fts_name; /* file name */ 140 size_t fts_namelen; /* strlen(fts_name) */ 141 long fts_level; /* depth (\-1 to N) */ 142 int fts_errno; /* file errno */ 143 long long fts_number; /* local numeric value */ 144 void *fts_pointer; /* local address value */ 145 struct ftsent *fts_parent; /* parent directory */ 146 struct ftsent *fts_link; /* next file structure */ 147 struct ftsent *fts_cycle; /* cycle structure */ 148 struct stat *fts_statp; /* stat(2) information */ 149} FTSENT; 150.Ed 151.Pp 152These fields are defined as follows: 153.Bl -tag -width "fts_namelen" 154.It Fa fts_info 155One of the following values describing the returned 156.Vt FTSENT 157structure and 158the file it represents. 159With the exception of directories without errors 160.Pq Dv FTS_D , 161all of these 162entries are terminal, that is, they will not be revisited, nor will any 163of their descendants be visited. 164.Bl -tag -width FTS_DEFAULT 165.It Dv FTS_D 166A directory being visited in pre-order. 167.It Dv FTS_DC 168A directory that causes a cycle in the tree. 169(The 170.Fa fts_cycle 171field of the 172.Vt FTSENT 173structure will be filled in as well.) 174.It Dv FTS_DEFAULT 175Any 176.Vt FTSENT 177structure that represents a file type not explicitly described 178by one of the other 179.Fa fts_info 180values. 181.It Dv FTS_DNR 182A directory which cannot be read. 183This immediately follows 184.Dv FTS_D , 185in place of 186.Dv FTS_DP , 187when the directory could not be entered, or could be entered but not 188read. 189This is an error return, and the 190.Fa fts_errno 191field will be set to indicate what caused the error. 192.It Dv FTS_DOT 193A file named 194.Ql .\& 195or 196.Ql ..\& 197which was not specified as a file name to 198.Fn fts_open 199or 200.Fn fts_open_b 201(see 202.Dv FTS_SEEDOT ) . 203.It Dv FTS_DP 204A directory being visited in post-order. 205The contents of the 206.Vt FTSENT 207structure will be unchanged from when 208the directory was visited in pre-order, except for the 209.Fa fts_info 210field. 211.It Dv FTS_ERR 212This is an error return, and the 213.Fa fts_errno 214field will be set to indicate what caused the error. 215.It Dv FTS_F 216A regular file. 217.It Dv FTS_NS 218A file for which no 219.Xr stat 2 220information was available. 221The contents of the 222.Fa fts_statp 223field are undefined. 224This is an error return, and the 225.Fa fts_errno 226field will be set to indicate what caused the error. 227.It Dv FTS_NSOK 228A file for which no 229.Xr stat 2 230information was requested. 231The contents of the 232.Fa fts_statp 233field are undefined. 234.It Dv FTS_SL 235A symbolic link. 236.It Dv FTS_SLNONE 237A symbolic link with a non-existent target. 238The contents of the 239.Fa fts_statp 240field reference the file characteristic information for the symbolic link 241itself. 242.El 243.It Fa fts_accpath 244A path for accessing the file from the current directory. 245.It Fa fts_path 246The path for the file relative to the root of the traversal. 247This path contains the path specified to 248.Fn fts_open 249or 250.Fn fts_open_b 251as a prefix. 252.It Fa fts_pathlen 253The length of the string referenced by 254.Fa fts_path . 255.It Fa fts_name 256The name of the file. 257.It Fa fts_namelen 258The length of the string referenced by 259.Fa fts_name . 260.It Fa fts_level 261The depth of the traversal, numbered from \-1 to N, where this file 262was found. 263The 264.Vt FTSENT 265structure representing the parent of the starting point (or root) 266of the traversal is numbered 267.Dv FTS_ROOTPARENTLEVEL 268(\-1), and the 269.Vt FTSENT 270structure for the root 271itself is numbered 272.Dv FTS_ROOTLEVEL 273(0). 274.It Fa fts_errno 275Upon return of a 276.Vt FTSENT 277structure from the 278.Fn fts_children 279or 280.Fn fts_read 281functions, with its 282.Fa fts_info 283field set to 284.Dv FTS_DNR , 285.Dv FTS_ERR 286or 287.Dv FTS_NS , 288the 289.Fa fts_errno 290field contains the value of the external variable 291.Va errno 292specifying the cause of the error. 293Otherwise, the contents of the 294.Fa fts_errno 295field are undefined. 296.It Fa fts_number 297This field is provided for the use of the application program and is 298not modified by the 299.Nm 300functions. 301It is initialized to 0. 302.It Fa fts_pointer 303This field is provided for the use of the application program and is 304not modified by the 305.Nm 306functions. 307It is initialized to 308.Dv NULL . 309.It Fa fts_parent 310A pointer to the 311.Vt FTSENT 312structure referencing the file in the hierarchy 313immediately above the current file, i.e., the directory of which this 314file is a member. 315A parent structure for the initial entry point is provided as well, 316however, only the 317.Fa fts_level , 318.Fa fts_number 319and 320.Fa fts_pointer 321fields are guaranteed to be initialized. 322.It Fa fts_link 323Upon return from the 324.Fn fts_children 325function, the 326.Fa fts_link 327field points to the next structure in the NULL-terminated linked list of 328directory members. 329Otherwise, the contents of the 330.Fa fts_link 331field are undefined. 332.It Fa fts_cycle 333If a directory causes a cycle in the hierarchy (see 334.Dv FTS_DC ) , 335either because 336of a hard link between two directories, or a symbolic link pointing to a 337directory, the 338.Fa fts_cycle 339field of the structure will point to the 340.Vt FTSENT 341structure in the hierarchy that references the same file as the current 342.Vt FTSENT 343structure. 344Otherwise, the contents of the 345.Fa fts_cycle 346field are undefined. 347.It Fa fts_statp 348A pointer to 349.Xr stat 2 350information for the file. 351.El 352.Pp 353A single buffer is used for all of the paths of all of the files in the 354file hierarchy. 355Therefore, the 356.Fa fts_path 357and 358.Fa fts_accpath 359fields are guaranteed to be 360.Dv NUL Ns -terminated 361.Em only 362for the file most recently returned by 363.Fn fts_read . 364To use these fields to reference any files represented by other 365.Vt FTSENT 366structures will require that the path buffer be modified using the 367information contained in that 368.Vt FTSENT 369structure's 370.Fa fts_pathlen 371field. 372Any such modifications should be undone before further calls to 373.Fn fts_read 374are attempted. 375The 376.Fa fts_name 377field is always 378.Dv NUL Ns -terminated . 379.Sh FTS_OPEN 380The 381.Fn fts_open 382function takes a pointer to an array of character pointers naming one 383or more paths which make up a logical file hierarchy to be traversed. 384The array must be terminated by a 385.Dv NULL 386pointer. 387.Pp 388There are 389a number of options, at least one of which (either 390.Dv FTS_LOGICAL 391or 392.Dv FTS_PHYSICAL ) 393must be specified. 394The options are selected by 395.Em or Ns 'ing 396the following values: 397.Bl -tag -width "FTS_COMFOLLOWDIR" 398.It Dv FTS_COMFOLLOW 399This option causes any symbolic link specified as a root path to be 400followed immediately whether or not 401.Dv FTS_LOGICAL 402is also specified. 403.It Dv FTS_COMFOLLOWDIR 404This option is similar to 405.Dv FTS_COMFOLLOW , 406but only follows symbolic links to directories. 407.It Dv FTS_LOGICAL 408This option causes the 409.Nm 410routines to return 411.Vt FTSENT 412structures for the targets of symbolic links 413instead of the symbolic links themselves. 414If this option is set, the only symbolic links for which 415.Vt FTSENT 416structures 417are returned to the application are those referencing non-existent files. 418Either 419.Dv FTS_LOGICAL 420or 421.Dv FTS_PHYSICAL 422.Em must 423be provided to the 424.Fn fts_open 425function. 426.It Dv FTS_NOCHDIR 427To allow descending to arbitrary depths 428(independent of 429.Brq Dv PATH_MAX ) 430and improve performance, the 431.Nm 432functions change directories as they walk the file hierarchy. 433This has the side-effect that an application cannot rely on being 434in any particular directory during the traversal. 435The 436.Dv FTS_NOCHDIR 437option turns off this feature, and the 438.Nm 439functions will not change the current directory. 440Note that applications should not themselves change their current directory 441and try to access files unless 442.Dv FTS_NOCHDIR 443is specified and absolute 444pathnames were provided as arguments to 445.Fn fts_open . 446.It Dv FTS_NOSTAT 447By default, returned 448.Vt FTSENT 449structures reference file characteristic information (the 450.Fa statp 451field) for each file visited. 452This option relaxes that requirement as a performance optimization, 453allowing the 454.Nm 455functions to set the 456.Fa fts_info 457field to 458.Dv FTS_NSOK 459and leave the contents of the 460.Fa statp 461field undefined. 462.It Dv FTS_NOSTAT_TYPE 463This option is similar to 464.Dv FTS_NOSTAT , 465but attempts to populate 466.Fa fts_info 467based on information from the 468.Fa d_type 469field of 470.Vt struct dirent . 471.It Dv FTS_PHYSICAL 472This option causes the 473.Nm 474routines to return 475.Vt FTSENT 476structures for symbolic links themselves instead 477of the target files they point to. 478If this option is set, 479.Vt FTSENT 480structures for all symbolic links in the 481hierarchy are returned to the application. 482Either 483.Dv FTS_LOGICAL 484or 485.Dv FTS_PHYSICAL 486.Em must 487be provided to the 488.Fn fts_open 489function. 490.It Dv FTS_SEEDOT 491By default, unless they are specified as path arguments to 492.Fn fts_open , 493any files named 494.Ql .\& 495or 496.Ql ..\& 497encountered in the file hierarchy are ignored. 498This option causes the 499.Nm 500routines to return 501.Vt FTSENT 502structures for them. 503.It Dv FTS_XDEV 504This option prevents 505.Nm 506from descending into directories that have a different device number 507than the file from which the descent began. 508.El 509.Pp 510The argument 511.Fn compar 512specifies a user-defined function which may be used to order the traversal 513of the hierarchy. 514It 515takes two pointers to pointers to 516.Vt FTSENT 517structures as arguments and 518should return a negative value, zero, or a positive value to indicate 519if the file referenced by its first argument comes before, in any order 520with respect to, or after, the file referenced by its second argument. 521The 522.Fa fts_accpath , 523.Fa fts_path 524and 525.Fa fts_pathlen 526fields of the 527.Vt FTSENT 528structures may 529.Em never 530be used in this comparison. 531If the 532.Fa fts_info 533field is set to 534.Dv FTS_NS 535or 536.Dv FTS_NSOK , 537the 538.Fa fts_statp 539field may not either. 540If the 541.Fn compar 542argument is 543.Dv NULL , 544the directory traversal order is in the order listed in 545.Fa path_argv 546for the root paths, and in the order listed in the directory for 547everything else. 548.Sh FTS_OPEN_B 549The 550.Fn fts_open_b 551function is identical to 552.Fn fts_open 553except that it takes a block pointer instead of a function pointer. 554The block is copied before 555.Fn fts_open_b 556returns, so the original can safely go out of scope or be released. 557.Sh FTS_READ 558The 559.Fn fts_read 560function returns a pointer to an 561.Vt FTSENT 562structure describing a file in 563the hierarchy. 564Directories (that are readable and do not cause cycles) are visited at 565least twice, once in pre-order and once in post-order. 566All other files are visited at least once. 567(Hard links between directories that do not cause cycles or symbolic 568links to symbolic links may cause files to be visited more than once, 569or directories more than twice.) 570.Pp 571If all the members of the hierarchy have been returned, 572.Fn fts_read 573returns 574.Dv NULL 575and sets the external variable 576.Va errno 577to 0. 578If an error unrelated to a file in the hierarchy occurs, 579.Fn fts_read 580returns 581.Dv NULL 582and sets 583.Va errno 584appropriately. 585If an error related to a returned file occurs, a pointer to an 586.Vt FTSENT 587structure is returned, and 588.Va errno 589may or may not have been set (see 590.Fa fts_info ) . 591.Pp 592The 593.Vt FTSENT 594structures returned by 595.Fn fts_read 596may be overwritten after a call to 597.Fn fts_close 598on the same file hierarchy stream, or, after a call to 599.Fn fts_read 600on the same file hierarchy stream unless they represent a file of type 601directory, in which case they will not be overwritten until after a call to 602.Fn fts_read 603after the 604.Vt FTSENT 605structure has been returned by the function 606.Fn fts_read 607in post-order. 608.Sh FTS_CHILDREN 609The 610.Fn fts_children 611function returns a pointer to an 612.Vt FTSENT 613structure describing the first entry in a NULL-terminated linked list of 614the files in the directory represented by the 615.Vt FTSENT 616structure most recently returned by 617.Fn fts_read . 618The list is linked through the 619.Fa fts_link 620field of the 621.Vt FTSENT 622structure, and is ordered by the user-specified comparison function, if any. 623Repeated calls to 624.Fn fts_children 625will recreate this linked list. 626.Pp 627As a special case, if 628.Fn fts_read 629has not yet been called for a hierarchy, 630.Fn fts_children 631will return a pointer to the files in the logical directory specified to 632.Fn fts_open 633or 634.Fn fts_open_b , 635i.e., the arguments specified to 636.Fn fts_open 637or 638.Fn fts_open_b . 639Otherwise, if the 640.Vt FTSENT 641structure most recently returned by 642.Fn fts_read 643is not a directory being visited in pre-order, 644or the directory does not contain any files, 645.Fn fts_children 646returns 647.Dv NULL 648and sets 649.Va errno 650to zero. 651If an error occurs, 652.Fn fts_children 653returns 654.Dv NULL 655and sets 656.Va errno 657appropriately. 658.Pp 659The 660.Vt FTSENT 661structures returned by 662.Fn fts_children 663may be overwritten after a call to 664.Fn fts_children , 665.Fn fts_close 666or 667.Fn fts_read 668on the same file hierarchy stream. 669.Pp 670.Em Option 671may be set to the following value: 672.Bl -tag -width FTS_NAMEONLY 673.It Dv FTS_NAMEONLY 674Only the names of the files are needed. 675The contents of all the fields in the returned linked list of structures 676are undefined with the exception of the 677.Fa fts_name 678and 679.Fa fts_namelen 680fields. 681.El 682.Sh FTS_SET 683The function 684.Fn fts_set 685allows the user application to determine further processing for the 686file 687.Fa f 688of the stream 689.Fa ftsp . 690The 691.Fn fts_set 692function 693returns 0 on success, and \-1 if an error occurs. 694.Em Option 695must be set to one of the following values: 696.Bl -tag -width FTS_PHYSICAL 697.It Dv FTS_AGAIN 698Re-visit the file; any file type may be re-visited. 699The next call to 700.Fn fts_read 701will return the referenced file. 702The 703.Fa fts_stat 704and 705.Fa fts_info 706fields of the structure will be reinitialized at that time, 707but no other fields will have been changed. 708This option is meaningful only for the most recently returned 709file from 710.Fn fts_read . 711Normal use is for post-order directory visits, where it causes the 712directory to be re-visited (in both pre and post-order) as well as all 713of its descendants. 714.It Dv FTS_FOLLOW 715The referenced file must be a symbolic link. 716If the referenced file is the one most recently returned by 717.Fn fts_read , 718the next call to 719.Fn fts_read 720returns the file with the 721.Fa fts_info 722and 723.Fa fts_statp 724fields reinitialized to reflect the target of the symbolic link instead 725of the symbolic link itself. 726If the file is one of those most recently returned by 727.Fn fts_children , 728the 729.Fa fts_info 730and 731.Fa fts_statp 732fields of the structure, when returned by 733.Fn fts_read , 734will reflect the target of the symbolic link instead of the symbolic link 735itself. 736In either case, if the target of the symbolic link does not exist the 737fields of the returned structure will be unchanged and the 738.Fa fts_info 739field will be set to 740.Dv FTS_SLNONE . 741.Pp 742If the target of the link is a directory, the pre-order return, followed 743by the return of all of its descendants, followed by a post-order return, 744is done. 745.It Dv FTS_SKIP 746No descendants of this file are visited. 747The file may be one of those most recently returned by either 748.Fn fts_children 749or 750.Fn fts_read . 751.El 752.Sh FTS_CLOSE 753The 754.Fn fts_close 755function closes a file hierarchy stream 756.Fa ftsp 757and restores the current directory to the directory from which 758.Fn fts_open 759or 760.Fn fts_open_b 761was called to open 762.Fa ftsp . 763The 764.Fn fts_close 765function 766returns 0 on success, and \-1 if an error occurs. 767.Sh ERRORS 768The 769.Fn fts_open 770and 771.Fn fts_open_b 772functions may fail and set 773.Va errno 774for any of the errors specified for the library functions 775.Xr open 2 776and 777.Xr malloc 3 . 778The 779.Fn fts_open_b 780function may also fail and set 781.Va errno 782to 783.Dv ENOSYS 784if the blocks runtime is missing. 785.Pp 786The 787.Fn fts_close 788function may fail and set 789.Va errno 790for any of the errors specified for the library functions 791.Xr chdir 2 792and 793.Xr close 2 . 794.Pp 795The 796.Fn fts_read 797and 798.Fn fts_children 799functions may fail and set 800.Va errno 801for any of the errors specified for the library functions 802.Xr chdir 2 , 803.Xr malloc 3 , 804.Xr opendir 3 , 805.Xr readdir 3 806and 807.Xr stat 2 . 808.Pp 809In addition, the 810.Fn fts_children , 811.Fn fts_open , 812and 813.Fn fts_set 814functions may fail and set 815.Va errno 816as follows: 817.Bl -tag -width Er 818.It Bq Er EINVAL 819The options were invalid, or the list were empty. 820.El 821.Sh SEE ALSO 822.Xr find 1 , 823.Xr chdir 2 , 824.Xr stat 2 , 825.Xr ftw 3 , 826.Xr qsort 3 827.Sh HISTORY 828The 829.Nm 830interface was first introduced in 831.Bx 4.4 . 832The 833.Fn fts_get_clientptr , 834.Fn fts_get_stream , 835and 836.Fn fts_set_clientptr 837functions were introduced in 838.Fx 5.0 , 839principally to provide for alternative interfaces to the 840.Nm 841functionality using different data structures. 842Blocks support and the 843.Dv FTS_COMFOLLOWDIR 844and 845.Dv FTS_NOSTAT 846options were added in 847.Fx 15.0 848based on similar functionality in macOS. 849.Sh BUGS 850The 851.Fn fts_open 852function will automatically set the 853.Dv FTS_NOCHDIR 854option if the 855.Dv FTS_LOGICAL 856option is provided, or if it cannot 857.Xr open 2 858the current directory. 859