My tree command for POSIX systems in C

I like the tree command. It’s nice to have when working with lots of directories and it brings an ‘graphic’ element to the command line 🙂 I’m here going to show a simple tree solution in C that I usually use as a base for more complicated implementations.

#include <string>
#include <dirent.h>

void rec_walker(const char *path, int level);
char* writer(int level);

int main(int argc, char const *argv[]) {

	DIR        *dir;
	const char *path;

	path = argv[1];

	// If no path set current path
	if (path == NULL) {
		path = ".";
	}

	// Test if dir  	
  	dir = opendir(path);
  	
  	if(dir) {  		
    	    rec_walker(path, 0);
  	}
  	else {
  		printf("%s is not a directory\n", argv[1]);
  		return 1;
  	}

	return 0;
}

Im here using the standard <string> library for common string operations and the dirent.h for easy access to the filesystem. First we have to define our external (not in main()) functions, rec_walker() and the writer() function (more about these later).
Then we set the path that we want to traverse. If no path from argv[] we set current directory as path. Now that we have a path we test to see if it is a directory and if it is we call the rec_walker() function:

void rec_walker(const char *path, int level){
	struct dirent *file;
	DIR *directory;
	
	chdir(path);
	
	directory = opendir(".");

	if(directory){
		while ((file = readdir(directory)) != NULL) {
	
			if (strcmp( file->d_name, "." ) != 0 && strcmp( file->d_name, ".." ) != 0) {			

				if (file->d_type == DT_DIR) {
					printf("%s%s:\n", writer(level + 1), file->d_name);
					rec_walker(file->d_name, level + 1);
				}
				else{
	      			printf("%s%s\n", writer(level), file->d_name);
	      		}
	      	}	
    	}
    	closedir(directory);
    }	

}

The rec_walker() function takes the path (as string) and a level (as int). The level variable is uses for a little ‘pretty print’. The rec_walker() function lists all files in the directory, and if the ‘file’ is a directory (DT_DIR) it will recursively call itself with the new path and an incremented level. It continues to do this until no directories are left.

Now we add a little ‘pretty print’ with the writer() function:

char* writer(int level){

	const char characters[] = "-----------------------------------";
	char result[] = "";

	// Max levels 
	if (level > 18)	{
		level = 18;
	}

	return strncat(result, characters, level * 2);

}

This function simply returns some lines to ‘indent’ the different levels to make it easier to read (very simple)

Example output from the above code:

--test:
--test_file.txt
----test_lvl2:
----test_file_lvl2.txt
treeplus
treeplus.c

Tested on gcc 4.2.1 and OSX 10.7.5

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>