Skip to content

Instantly share code, notes, and snippets.

@jtpaasch
Last active August 29, 2015 13:56
Show Gist options
  • Select an option

  • Save jtpaasch/9007775 to your computer and use it in GitHub Desktop.

Select an option

Save jtpaasch/9007775 to your computer and use it in GitHub Desktop.
Walk a directory up or down, looking for a file or folder.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
/*
* A NON-CONSTANT VARIABLE
* THAT CAN BE SET BY THE FIND_UP() FUNCTION
*/
char found_path[1024];
/*
* Function PROTOTYPES.
*/
int find_up(char *path, char *target);
int find_down(char *path, char *target);
/*
* The MAIN entry point into the program.
* That is to say, this function runs first.
*
* @return int Status code
*/
int main(void) {
// What is the path?
char path[100];
path[0] = '\0';
strcat(path, "./test");
// What are we looking for?
char target[100];
target[0] = '\0';
strcat(target, "foo.txt");
// Can we find it?
int success = find_up(path, target);
if (success) {
puts("We found it: ");
puts(found_path);
} else {
puts("Not found");
}
// Exit cleanly.
return 0;
}
/*
* Walk a directory tree up, looking for
* a file/directory that matches the specified path.
*
* @return int
*/
int find_up(char *path, char *target) {
DIR *stream;
struct dirent *item;
// Open the directory.
stream = opendir(path);
if (stream != NULL) {
// Check each item in the directory.
while ((item = readdir(stream))) {
// Ignore "." and ".." items.
if (strcmp(item->d_name, ".") == 0 || strcmp(item->d_name, "..") == 0) {
continue;
}
// Is this the item we're looking for?
if (strcmp(item->d_name, target) == 0) {
// Store the path as "found_path".
found_path[0] = '\0';
strcat(found_path, path);
strcat(found_path, "/");
strcat(found_path, target);
return 1;
}
}
// What's the path to the parent directory?
char parent_directory[strlen(path) + 4];
char full_path[1024];
parent_directory[0] = '\0';
strcat(parent_directory, path);
strcat(parent_directory, "/../");
// If there is a parent directory, check it.
int success;
realpath(parent_directory, full_path);
if (strcmp(full_path, "/") == 0) {
success = 0;
} else {
success = find_up(full_path, target);
}
// Close the stream and return the results.
(void) closedir(stream);
return success;
}
// If we couldn't open the directory, let's print an error.
else {
return 0;
}
}
/*
* Walk a directory tree down, looking for
* a file/directory that matches the specified path.
*
* @return int
*/
int find_down(char *path, char *target) {
// We need to store our directory stream in a DIR object.
DIR *stream;
// We need to store items in the directory in a "dirent" struct.
struct dirent *item;
// We need to store info about files in a "stat" struct.
struct stat info;
// Open the current directory.
stream = opendir(path);
// Did we get a valid stream? Let's make sure the stream isn't NULL.
if (stream != NULL) {
// Read the stream, one item at a time.
while ((item = readdir(stream))) {
// Ignore "." and ".." items.
if (strcmp(item->d_name, ".") == 0 || strcmp(item->d_name, "..") == 0) {
continue;
}
// Is it the item we're looking for?
if (strcmp(item->d_name, target) == 0) {
return 1;
}
// If not, keep searching.
else {
// Generate a path for this file.
char full_path[1024];
full_path[0] = '\0';
strcat(full_path, path);
strcat(full_path, "/");
strcat(full_path, item->d_name);
// Can we get some info about the item?
if (stat(full_path, &info) == 0) {
// Is it a directory? If so, look in it.
if (info.st_mode & S_IFDIR) {
int success = find_down(full_path, target);
// Did we find what we're looking for?
if (success) {
return 1;
}
}
}
// if we got no info, report the error.
else {
printf("Could not stat the file: %s", full_path);
}
}
}
// Be sure to close our stream.
(void) closedir(stream);
return 0;
}
// If we couldn't open the directory, let's print an error.
else {
printf("Could not open the directory: %s", path);
return 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment