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 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