Traversing a Filesystem with fts(3)
If you are only interested in traversing all directories and files for the specified path(s), just repeatedly call fts_read
.
If you want to only iterate through the stream, @sehe's example could be rewritten as:
#include<stdlib.h>#include<stdio.h>#include<sys/types.h>#include<fts.h>#include<string.h>#include<errno.h>int compare (const FTSENT**, const FTSENT**);void indent (int i);int main(int argc, char* const argv[]){ FTS* file_system = NULL; FTSENT *node, = NULL; if (argc<2) { printf("Usage: %s <path-spec>\n", argv[0]); exit(255); } file_system = fts_open(argv + 1,FTS_COMFOLLOW|FTS_NOCHDIR,&compare); if (NULL != file_system) { while( (node = fts_read(file_system)) != NULL) { switch (node->fts_info) { case FTS_D : case FTS_F : case FTS_SL: indent(node->fts_level); printf("%s\n", node->fts_name); break; default: break; } } fts_close(file_system); } return 0;}int compare(const FTSENT** one, const FTSENT** two){ return (strcmp((*one)->fts_name, (*two)->fts_name));}void indent(int i){ for (; i > 0; i--) printf(" ");}
When you run it, it iterates through the stream and lists all files and directories in order:
★ mkdir -p test/A/1 test/A/2 test/B/1 test/B/2★ tree test test├── A│ ├── 1│ └── 2└── B ├── 1 └── 2★ ./fts test test A 1 2 B 1 2
Call fts_children
only if you want a list of child nodes of a specific directory. In that case you must call fts_read
at least once before calling fts_children
; otherwise fts_children
will only return nodes specified in argv
parameter to fts_open
.
You simply need to add a NULL check.
You might want to
- add one for
file_system
- check for command line arguments
Add more errorhandling:
The
fts_children()
function returns a pointer to anFTSENT
structure describing the first entry in aNULL
terminated linked list of files in the directory, if successful. Thefts_children()
function may fail and seterrno
for any of the errors that thechdir()
,malloc()
,opendir()
,readdir()
, andstat()
functions specify.
Update To the new question(s) in the comment:
- The while loop for linked list traversal was misplaced (outside the outer loop?)
- The printf displayed only the path... not the filename.
while you're at it:
#include<stdlib.h>#include<stdio.h>#include<sys/types.h>#include<sys/stat.h>#include<fts.h>#include<string.h>#include<errno.h>int compare (const FTSENT**, const FTSENT**);int main(int argc, char* const argv[]){ FTS* file_system = NULL; FTSENT* child = NULL; FTSENT* parent = NULL; if (argc<2) { printf("Usage: %s <path-spec>\n", argv[0]); exit(255); } file_system = fts_open(argv + 1,FTS_COMFOLLOW | FTS_NOCHDIR,&compare); if (NULL != file_system) { while( (parent = fts_read(file_system)) != NULL) { child = fts_children(file_system,0); if (errno != 0) { perror("fts_children"); } while ((NULL != child) && (NULL != child->fts_link)) { child = child->fts_link; printf("%s%s\n", child->fts_path, child->fts_name); } } fts_close(file_system); } return 0;}int compare(const FTSENT** one, const FTSENT** two){ return (strcmp((*one)->fts_name, (*two)->fts_name));}
Sample output fragment:
./.profiles/sehe/.opera/icons/cache/g_0000./.profiles/sehe/.opera/icons/cache/g_0000/opr00002.tmp./.profiles/sehe/.opera/icons/cache/g_0000/opr00003.tmp./.profiles/sehe/home/sehe/.mozillafts_children: Permission denied./.vbox-sehe-ipc/lock