'C directory traversal - printing directory names it shouldn't be

This is probably just a syntax thing that I'm doing wrong, but I can't for the life of me figure it out, so I apologize if this is too "HEY DEBUG MY CODE FOR ME!"

Relevant code:

struct dirent *readDir;
DIR *dir;
dir = opendir(name);

if(dir == NULL) {
    printf("No directory found with the name %s\n", name);
} else {
    printf("directory named %s opened.\n", name);

    while((readDir = readdir(dir)) != NULL) {
        if(readDir->d_name != ".." || readDir->d_name != ".") {
            printf("%s\n", readDir->d_name);
        }
    }
    closedir(dir);
}

The if condition in the while loop doesn't seem to work, here's the output it produces:

directory named test opened.
file2
.
test2
file1
..

If I'm not mistaking, the if statement should filter out the . and .. directories, but it doesn't. The goal of this is to be a recursive directory traversal, but unless I can keep it from recursing into the . and .. directories I can't really move on.

Basically, I don't know how to do string comparing I guess?

c


Solution 1:[1]

C does not support '!=' or '==' for string comparison. Use strcmp();

if(readDir->d_name != ".." || readDir->d_name != ".") {

Should be

if(strcmp(readDir->d_name, "..") && strcmp(readDir->d_name, ".")) {
    // d_name is not "." or ".."
}

Solution 2:[2]

There are two problems with the following:

if(readDir->d_name != ".." || readDir->d_name != ".") {

First, you cannot compare strings this way in C... you're essentially checking whether the address of the string literal matches the address in readDir->d_name. You need to use a function like strcmp() instead.

Second, when you OR the conditions like that, only one needs to be true to make the whole expression true... and since d_name can't equal ".." AND "." simultaneously, the overall expression would always be TRUE even if the string comparisons did work as you (probably) expected.

So you need something like:

if (strcmp("..", readDir->d_name) && strcmp(".", readDir->d_name)) {

(since strcmp() returns non-zero when the strings don't match, and you need to not match both strings).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Charlie Burns
Solution 2 Dmitri