0

In this code, I am getting all the subdirectories paths from a directory. It is working fine but I want to add something more and that is to count all the subdirectories and print them. How to do this in this function. I used the count variable to make it work but the result is like this.

Given result:

/home/runner/TestC1/file
15775232
/home/runner/TestC1/dsf
15775233
/home/runner/TestC1/main.c
15775234
/home/runner/TestC1/main
15775235

Expected result:

/home/runner/TestC1/file
/home/runner/TestC1/dsf
/home/runner/TestC1/main.c
/home/runner/TestC1/main

Counted: 4 subdirectories.

Code

void listdir(void){
    DIR *dir;
    struct dirent *entry;
    size_t count;

    if (!(dir = opendir(path))) {  
        perror ("opendir-path not found");
        return;
    }

    while ((entry = readdir(dir)) != NULL) {  
        char *name = entry->d_name;
        if (entry->d_type == DT_DIR)  
            if (!strcmp(name, ".") || !strcmp(name, ".."))
                continue;
        snprintf (path1, 100, "%s/%s\n", path, name);
        printf("%s", path1);
        printf("%zu\n", count);
        count++;
    }
    closedir (dir); 
}
Sky wifibrand
  • 109
  • 1
  • 6
  • 3
    You didn't initialize `count`. And you are printing inside the loop. – Thomas Feb 22 '21 at 15:00
  • 3
    You should only count directories according to the title of the question. You code counts every file as well as sub-directories. Put an else block after the inner if and increment count there. Initialize `count` too, as already pointed out. IMO, you need braces after the outer `if` too. The current nested if could (maybe even should) be written as `if (A && (B || C))`, but you're about to need to change it so that you do need the two levels of operation. – Jonathan Leffler Feb 22 '21 at 15:04
  • 1
    `"opendir-path not found"` is going to lead to very confusing error messages like `opendir-path not found: permission denied`. Just write `perror(path);` – William Pursell Feb 22 '21 at 15:09

1 Answers1

6

There are a few problems with your code:

As Thomas says above:

You didn't initialize count. And you are printing inside the loop

  1. You do not initialize count to zero.
  2. You print inside the loop.
  3. You count everything except . and .., without checking whether it is a file or a directory

Here's a (hopefully) fixed version of your code

void listdir(void){
    DIR *dir;
    struct dirent *entry;
    unsigned count = 0;

    if (!(dir = opendir(path))) {  
        perror ("opendir-path not found");
        return;
    }

    while ((entry = readdir(dir)) != NULL) {  
        char *name = entry->d_name;
        if (entry->d_type == DT_DIR) {
            if (!strcmp(name, ".") || !strcmp(name, ".."))
                continue;
            count++;
            snprintf (path1, 100, "%s/%s\n", path, name);
            printf("%s", path1);
        }
    }
    printf("\nCounted: %u subdirectories.\n", count);
    closedir (dir); 
}

Edit: Edited my code following the comment by chux-ReinstateMonica

Minor: Little reason for size_t count when unsigned count is certainly fine. size_t depends on memory - not file space. Pedantically could use uintmax_t. IAC, "%d" is not the specified matching specifier to go with size_t - a step backwards from OP's matching "%zu"

Adalcar
  • 1,458
  • 11
  • 26
  • 2
    @chux-ReinstateMonica Thank you, was used to using `size_t` for any unsigned data. (Assuming he isn't working on a filesystem from some martian futuristic civilization where file you store billions of files in the same directory, I doubt `uintmax_t` is absolutely necessary) – Adalcar Feb 22 '21 at 15:42
  • [How many files can I put in a directory?](https://stackoverflow.com/q/466521/2410359) might be an interesting read to assess the type for `count`. – chux - Reinstate Monica Feb 22 '21 at 18:53