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 May 7, 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 is an error return, and the 184.Fa fts_errno 185field will be set to indicate what caused the error. 186.It Dv FTS_DOT 187A file named 188.Ql .\& 189or 190.Ql ..\& 191which was not specified as a file name to 192.Fn fts_open 193or 194.Fn fts_open_b 195(see 196.Dv FTS_SEEDOT ) . 197.It Dv FTS_DP 198A directory being visited in post-order. 199The contents of the 200.Vt FTSENT 201structure will be unchanged from when 202the directory was visited in pre-order, except for the 203.Fa fts_info 204field. 205.It Dv FTS_ERR 206This is an error return, and the 207.Fa fts_errno 208field will be set to indicate what caused the error. 209.It Dv FTS_F 210A regular file. 211.It Dv FTS_NS 212A file for which no 213.Xr stat 2 214information was available. 215The contents of the 216.Fa fts_statp 217field are undefined. 218This is an error return, and the 219.Fa fts_errno 220field will be set to indicate what caused the error. 221.It Dv FTS_NSOK 222A file for which no 223.Xr stat 2 224information was requested. 225The contents of the 226.Fa fts_statp 227field are undefined. 228.It Dv FTS_SL 229A symbolic link. 230.It Dv FTS_SLNONE 231A symbolic link with a non-existent target. 232The contents of the 233.Fa fts_statp 234field reference the file characteristic information for the symbolic link 235itself. 236.El 237.It Fa fts_accpath 238A path for accessing the file from the current directory. 239.It Fa fts_path 240The path for the file relative to the root of the traversal. 241This path contains the path specified to 242.Fn fts_open 243or 244.Fn fts_open_b 245as a prefix. 246.It Fa fts_pathlen 247The length of the string referenced by 248.Fa fts_path . 249.It Fa fts_name 250The name of the file. 251.It Fa fts_namelen 252The length of the string referenced by 253.Fa fts_name . 254.It Fa fts_level 255The depth of the traversal, numbered from \-1 to N, where this file 256was found. 257The 258.Vt FTSENT 259structure representing the parent of the starting point (or root) 260of the traversal is numbered 261.Dv FTS_ROOTPARENTLEVEL 262(\-1), and the 263.Vt FTSENT 264structure for the root 265itself is numbered 266.Dv FTS_ROOTLEVEL 267(0). 268.It Fa fts_errno 269Upon return of a 270.Vt FTSENT 271structure from the 272.Fn fts_children 273or 274.Fn fts_read 275functions, with its 276.Fa fts_info 277field set to 278.Dv FTS_DNR , 279.Dv FTS_ERR 280or 281.Dv FTS_NS , 282the 283.Fa fts_errno 284field contains the value of the external variable 285.Va errno 286specifying the cause of the error. 287Otherwise, the contents of the 288.Fa fts_errno 289field are undefined. 290.It Fa fts_number 291This field is provided for the use of the application program and is 292not modified by the 293.Nm 294functions. 295It is initialized to 0. 296.It Fa fts_pointer 297This field is provided for the use of the application program and is 298not modified by the 299.Nm 300functions. 301It is initialized to 302.Dv NULL . 303.It Fa fts_parent 304A pointer to the 305.Vt FTSENT 306structure referencing the file in the hierarchy 307immediately above the current file, i.e., the directory of which this 308file is a member. 309A parent structure for the initial entry point is provided as well, 310however, only the 311.Fa fts_level , 312.Fa fts_number 313and 314.Fa fts_pointer 315fields are guaranteed to be initialized. 316.It Fa fts_link 317Upon return from the 318.Fn fts_children 319function, the 320.Fa fts_link 321field points to the next structure in the NULL-terminated linked list of 322directory members. 323Otherwise, the contents of the 324.Fa fts_link 325field are undefined. 326.It Fa fts_cycle 327If a directory causes a cycle in the hierarchy (see 328.Dv FTS_DC ) , 329either because 330of a hard link between two directories, or a symbolic link pointing to a 331directory, the 332.Fa fts_cycle 333field of the structure will point to the 334.Vt FTSENT 335structure in the hierarchy that references the same file as the current 336.Vt FTSENT 337structure. 338Otherwise, the contents of the 339.Fa fts_cycle 340field are undefined. 341.It Fa fts_statp 342A pointer to 343.Xr stat 2 344information for the file. 345.El 346.Pp 347A single buffer is used for all of the paths of all of the files in the 348file hierarchy. 349Therefore, the 350.Fa fts_path 351and 352.Fa fts_accpath 353fields are guaranteed to be 354.Dv NUL Ns -terminated 355.Em only 356for the file most recently returned by 357.Fn fts_read . 358To use these fields to reference any files represented by other 359.Vt FTSENT 360structures will require that the path buffer be modified using the 361information contained in that 362.Vt FTSENT 363structure's 364.Fa fts_pathlen 365field. 366Any such modifications should be undone before further calls to 367.Fn fts_read 368are attempted. 369The 370.Fa fts_name 371field is always 372.Dv NUL Ns -terminated . 373.Sh FTS_OPEN 374The 375.Fn fts_open 376function takes a pointer to an array of character pointers naming one 377or more paths which make up a logical file hierarchy to be traversed. 378The array must be terminated by a 379.Dv NULL 380pointer. 381.Pp 382There are 383a number of options, at least one of which (either 384.Dv FTS_LOGICAL 385or 386.Dv FTS_PHYSICAL ) 387must be specified. 388The options are selected by 389.Em or Ns 'ing 390the following values: 391.Bl -tag -width "FTS_PHYSICAL" 392.It Dv FTS_COMFOLLOW 393This option causes any symbolic link specified as a root path to be 394followed immediately whether or not 395.Dv FTS_LOGICAL 396is also specified. 397.It Dv FTS_COMFOLLOWDIR 398This option is similar to 399.Dv FTS_COMFOLLOW , 400but only follows symbolic links to directories. 401.It Dv FTS_LOGICAL 402This option causes the 403.Nm 404routines to return 405.Vt FTSENT 406structures for the targets of symbolic links 407instead of the symbolic links themselves. 408If this option is set, the only symbolic links for which 409.Vt FTSENT 410structures 411are returned to the application are those referencing non-existent files. 412Either 413.Dv FTS_LOGICAL 414or 415.Dv FTS_PHYSICAL 416.Em must 417be provided to the 418.Fn fts_open 419function. 420.It Dv FTS_NOCHDIR 421To allow descending to arbitrary depths 422(independent of 423.Brq Dv PATH_MAX ) 424and improve performance, the 425.Nm 426functions change directories as they walk the file hierarchy. 427This has the side-effect that an application cannot rely on being 428in any particular directory during the traversal. 429The 430.Dv FTS_NOCHDIR 431option turns off this feature, and the 432.Nm 433functions will not change the current directory. 434Note that applications should not themselves change their current directory 435and try to access files unless 436.Dv FTS_NOCHDIR 437is specified and absolute 438pathnames were provided as arguments to 439.Fn fts_open . 440.It Dv FTS_NOSTAT 441By default, returned 442.Vt FTSENT 443structures reference file characteristic information (the 444.Fa statp 445field) for each file visited. 446This option relaxes that requirement as a performance optimization, 447allowing the 448.Nm 449functions to set the 450.Fa fts_info 451field to 452.Dv FTS_NSOK 453and leave the contents of the 454.Fa statp 455field undefined. 456.It Dv FTS_NOSTAT_TYPE 457This option is similar to 458.Dv FTS_NOSTAT , 459but attempts to populate 460.Fa fts_info 461based on information from the 462.Fa d_type 463field of 464.Vt struct dirent . 465.It Dv FTS_PHYSICAL 466This option causes the 467.Nm 468routines to return 469.Vt FTSENT 470structures for symbolic links themselves instead 471of the target files they point to. 472If this option is set, 473.Vt FTSENT 474structures for all symbolic links in the 475hierarchy are returned to the application. 476Either 477.Dv FTS_LOGICAL 478or 479.Dv FTS_PHYSICAL 480.Em must 481be provided to the 482.Fn fts_open 483function. 484.It Dv FTS_SEEDOT 485By default, unless they are specified as path arguments to 486.Fn fts_open , 487any files named 488.Ql .\& 489or 490.Ql ..\& 491encountered in the file hierarchy are ignored. 492This option causes the 493.Nm 494routines to return 495.Vt FTSENT 496structures for them. 497.It Dv FTS_XDEV 498This option prevents 499.Nm 500from descending into directories that have a different device number 501than the file from which the descent began. 502.El 503.Pp 504The argument 505.Fn compar 506specifies a user-defined function which may be used to order the traversal 507of the hierarchy. 508It 509takes two pointers to pointers to 510.Vt FTSENT 511structures as arguments and 512should return a negative value, zero, or a positive value to indicate 513if the file referenced by its first argument comes before, in any order 514with respect to, or after, the file referenced by its second argument. 515The 516.Fa fts_accpath , 517.Fa fts_path 518and 519.Fa fts_pathlen 520fields of the 521.Vt FTSENT 522structures may 523.Em never 524be used in this comparison. 525If the 526.Fa fts_info 527field is set to 528.Dv FTS_NS 529or 530.Dv FTS_NSOK , 531the 532.Fa fts_statp 533field may not either. 534If the 535.Fn compar 536argument is 537.Dv NULL , 538the directory traversal order is in the order listed in 539.Fa path_argv 540for the root paths, and in the order listed in the directory for 541everything else. 542.Sh FTS_OPEN_B 543The 544.Fn fts_open_b 545function is identical to 546.Fn fts_open 547except that it takes a block pointer instead of a function pointer. 548The block is copied before 549.Fn fts_open_b 550returns, so the original can safely go out of scope or be released. 551.Sh FTS_READ 552The 553.Fn fts_read 554function returns a pointer to an 555.Vt FTSENT 556structure describing a file in 557the hierarchy. 558Directories (that are readable and do not cause cycles) are visited at 559least twice, once in pre-order and once in post-order. 560All other files are visited at least once. 561(Hard links between directories that do not cause cycles or symbolic 562links to symbolic links may cause files to be visited more than once, 563or directories more than twice.) 564.Pp 565If all the members of the hierarchy have been returned, 566.Fn fts_read 567returns 568.Dv NULL 569and sets the external variable 570.Va errno 571to 0. 572If an error unrelated to a file in the hierarchy occurs, 573.Fn fts_read 574returns 575.Dv NULL 576and sets 577.Va errno 578appropriately. 579If an error related to a returned file occurs, a pointer to an 580.Vt FTSENT 581structure is returned, and 582.Va errno 583may or may not have been set (see 584.Fa fts_info ) . 585.Pp 586The 587.Vt FTSENT 588structures returned by 589.Fn fts_read 590may be overwritten after a call to 591.Fn fts_close 592on the same file hierarchy stream, or, after a call to 593.Fn fts_read 594on the same file hierarchy stream unless they represent a file of type 595directory, in which case they will not be overwritten until after a call to 596.Fn fts_read 597after the 598.Vt FTSENT 599structure has been returned by the function 600.Fn fts_read 601in post-order. 602.Sh FTS_CHILDREN 603The 604.Fn fts_children 605function returns a pointer to an 606.Vt FTSENT 607structure describing the first entry in a NULL-terminated linked list of 608the files in the directory represented by the 609.Vt FTSENT 610structure most recently returned by 611.Fn fts_read . 612The list is linked through the 613.Fa fts_link 614field of the 615.Vt FTSENT 616structure, and is ordered by the user-specified comparison function, if any. 617Repeated calls to 618.Fn fts_children 619will recreate this linked list. 620.Pp 621As a special case, if 622.Fn fts_read 623has not yet been called for a hierarchy, 624.Fn fts_children 625will return a pointer to the files in the logical directory specified to 626.Fn fts_open 627or 628.Fn fts_open_b , 629i.e., the arguments specified to 630.Fn fts_open 631or 632.Fn fts_open_b . 633Otherwise, if the 634.Vt FTSENT 635structure most recently returned by 636.Fn fts_read 637is not a directory being visited in pre-order, 638or the directory does not contain any files, 639.Fn fts_children 640returns 641.Dv NULL 642and sets 643.Va errno 644to zero. 645If an error occurs, 646.Fn fts_children 647returns 648.Dv NULL 649and sets 650.Va errno 651appropriately. 652.Pp 653The 654.Vt FTSENT 655structures returned by 656.Fn fts_children 657may be overwritten after a call to 658.Fn fts_children , 659.Fn fts_close 660or 661.Fn fts_read 662on the same file hierarchy stream. 663.Pp 664.Em Option 665may be set to the following value: 666.Bl -tag -width FTS_NAMEONLY 667.It Dv FTS_NAMEONLY 668Only the names of the files are needed. 669The contents of all the fields in the returned linked list of structures 670are undefined with the exception of the 671.Fa fts_name 672and 673.Fa fts_namelen 674fields. 675.El 676.Sh FTS_SET 677The function 678.Fn fts_set 679allows the user application to determine further processing for the 680file 681.Fa f 682of the stream 683.Fa ftsp . 684The 685.Fn fts_set 686function 687returns 0 on success, and \-1 if an error occurs. 688.Em Option 689must be set to one of the following values: 690.Bl -tag -width FTS_PHYSICAL 691.It Dv FTS_AGAIN 692Re-visit the file; any file type may be re-visited. 693The next call to 694.Fn fts_read 695will return the referenced file. 696The 697.Fa fts_stat 698and 699.Fa fts_info 700fields of the structure will be reinitialized at that time, 701but no other fields will have been changed. 702This option is meaningful only for the most recently returned 703file from 704.Fn fts_read . 705Normal use is for post-order directory visits, where it causes the 706directory to be re-visited (in both pre and post-order) as well as all 707of its descendants. 708.It Dv FTS_FOLLOW 709The referenced file must be a symbolic link. 710If the referenced file is the one most recently returned by 711.Fn fts_read , 712the next call to 713.Fn fts_read 714returns the file with the 715.Fa fts_info 716and 717.Fa fts_statp 718fields reinitialized to reflect the target of the symbolic link instead 719of the symbolic link itself. 720If the file is one of those most recently returned by 721.Fn fts_children , 722the 723.Fa fts_info 724and 725.Fa fts_statp 726fields of the structure, when returned by 727.Fn fts_read , 728will reflect the target of the symbolic link instead of the symbolic link 729itself. 730In either case, if the target of the symbolic link does not exist the 731fields of the returned structure will be unchanged and the 732.Fa fts_info 733field will be set to 734.Dv FTS_SLNONE . 735.Pp 736If the target of the link is a directory, the pre-order return, followed 737by the return of all of its descendants, followed by a post-order return, 738is done. 739.It Dv FTS_SKIP 740No descendants of this file are visited. 741The file may be one of those most recently returned by either 742.Fn fts_children 743or 744.Fn fts_read . 745.El 746.Sh FTS_CLOSE 747The 748.Fn fts_close 749function closes a file hierarchy stream 750.Fa ftsp 751and restores the current directory to the directory from which 752.Fn fts_open 753or 754.Fn fts_open_b 755was called to open 756.Fa ftsp . 757The 758.Fn fts_close 759function 760returns 0 on success, and \-1 if an error occurs. 761.Sh ERRORS 762The 763.Fn fts_open 764and 765.Fn fts_open_b 766functions may fail and set 767.Va errno 768for any of the errors specified for the library functions 769.Xr open 2 770and 771.Xr malloc 3 . 772The 773.Fn fts_open_b 774function may also fail and set 775.Va errno 776to 777.Dv ENOSYS 778if the blocks runtime is missing. 779.Pp 780The 781.Fn fts_close 782function may fail and set 783.Va errno 784for any of the errors specified for the library functions 785.Xr chdir 2 786and 787.Xr close 2 . 788.Pp 789The 790.Fn fts_read 791and 792.Fn fts_children 793functions may fail and set 794.Va errno 795for any of the errors specified for the library functions 796.Xr chdir 2 , 797.Xr malloc 3 , 798.Xr opendir 3 , 799.Xr readdir 3 800and 801.Xr stat 2 . 802.Pp 803In addition, the 804.Fn fts_children , 805.Fn fts_open , 806and 807.Fn fts_set 808functions may fail and set 809.Va errno 810as follows: 811.Bl -tag -width Er 812.It Bq Er EINVAL 813The options were invalid, or the list were empty. 814.El 815.Sh SEE ALSO 816.Xr find 1 , 817.Xr chdir 2 , 818.Xr stat 2 , 819.Xr ftw 3 , 820.Xr qsort 3 821.Sh HISTORY 822The 823.Nm 824interface was first introduced in 825.Bx 4.4 . 826The 827.Fn fts_get_clientptr , 828.Fn fts_get_stream , 829and 830.Fn fts_set_clientptr 831functions were introduced in 832.Fx 5.0 , 833principally to provide for alternative interfaces to the 834.Nm 835functionality using different data structures. 836Blocks support and the 837.Dv FTS_COMFOLLOWDIR 838and 839.Dv FTS_NOSTAT 840options were added in 841.Fx 15.0 842based on similar functionality in macOS. 843.Sh BUGS 844The 845.Fn fts_open 846function will automatically set the 847.Dv FTS_NOCHDIR 848option if the 849.Dv FTS_LOGICAL 850option is provided, or if it cannot 851.Xr open 2 852the current directory. 853