A Recursive Directory-Scanning Program

The program printdir.c prints out the specified directory and recurse through subdirectories, using the depth parameter for indendation.

The program produces output like this (edited for brevity):

>./printdir .
Directory scan of .
ls2
Makefile
ls2.c
subDir1/
    subDir2/
        subDir3/
printdir
printdir.c
prog.sh
done.

Most of the action is within the printdir function. After some initial error checking using opendir to see if the directory exists, printdir makes a call to chdir to the directory specified. While entries returned by readdir exist, the program checks to see whether the entry is a directory. If it isn't, it prints an indented file entry

If the entry is a directory, the printdir function calls itself (recursion) with the subdirectory name. Recursion ends when there are no more subdirectories to process. Then the current directory is closed via closedir(dir> and the call chdir("..") takes it back up the directory tree and the previous listing can continue.

The main program uses a command argument for the starting directory name, if one is available. The default directory is ".".

Reference

Neil Matthew and Richard Stone, Beginning Linux Programming, Third Edition, Wrox, 2004. ISBN 0-7645-4497-7. Chapter 3, p 122-125

Source for printdir.c

/*  We start with the appropriate headers and then a function, printdir,
*    which prints out the current directory.
*    It will recurse for subdirectories, using the depth parameter for indentation.
*
*	Matthew and Stones, chapter 3, p 122-125
*/

#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>


void printdir(char *dir, int depth)
{
    DIR *dp;
    struct dirent *entry;
    struct stat statbuf;
	int spaces = depth*4;

    if((dp = opendir(dir)) == NULL) {
        fprintf(stderr,"cannot open directory: %s\n", dir);
        return;
    }
    chdir(dir);
    while((entry = readdir(dp)) != NULL) {
        lstat(entry->d_name,&statbuf);
        if(S_ISDIR(statbuf.st_mode)) {
            /* Found a directory, but ignore . and .. */
            if(strcmp(".",entry->d_name) == 0 || 
                strcmp("..",entry->d_name) == 0)
                continue;
            printf("%*s%s/\n",spaces,"",entry->d_name);
            /* Recurse at a new indent level */
            printdir(entry->d_name,depth+1);
        }
        else printf("%*s%s\n",spaces,"",entry->d_name);
    }
    chdir("..");
    closedir(dp);
}

/*  Now we move onto the main function.  */

int main(int argc, char* argv[])
{
    char *topdir, pwd[2]=".";
    if (argc != 2)
        topdir=pwd;
    else
        topdir=argv[1];

    printf("Directory scan of %s\n",topdir);
    printdir(topdir,0);
    printf("done.\n");

    return 0;
}


Maintained by John Loomis, last updated 27 September 2006