C: recursively open subdirectories and create new files

I am writing something that recursively finds .c and .h files and removes all comments (just like a training exercise). For each .c / .h file found, this program creates an additional file, which is equal to the original file without comments. So, for example, "helloworld.c" will lead to an additional file "__helloworld.c"

The problem I am facing is this:

I have a loop that iterates over all the entries in the directory and continues to work until it stops finding files with the extensions .c or .h. However, the cycle never ends, since each time a file is found, another is created. So I have a recursive situation where __helloworld.c becomes ____ helloworld.c, which becomes ____ helloworld.c, etc. (in case someone suggests, yes, for new files you must have the extension .c). One of the possible solutions could be tracking the numbers of the inodes, so we only know to iterate over the source files, however, this requires several iterations of the loop: once to count entries in the directory (and use this number to initialize the array for inode nums),twice for storing the numbers of the inodes and finally, for the third time to complete the work.

Can anyone share ideas that could achieve this in one run of the cycle? the code breaks into two files, so I published the main recursive procedure:

consume_comments(): takes one file as an argument, creates a new file with comments omitted

My main procedure pretty much simply handles some arguments - the procedure below is a real problem.

/*
opens a directory stream of the dir pointed to by 'filename',
looks for .c .h files, consumes comments. If 'rc' == 1, find()
calls itself when it encounters a sub-directory.
*/
int find (const char * dirname)
{
        int count = 3;
        DIR * dh;
        struct dirent * dent;
        struct stat buf;
        const char * fnext;
        int filecount = 0;

        chdir(dirname);

        if ((dh = opendir(".")) == NULL)
        {
                printf("Error opening directory \"%s\"\n", dirname);
                exit(-1);
        }

        while ((dent = readdir(dh)) != NULL)
        {
                if (count) count--;
                if (!count)
                {
                        if (lstat(dent->d_name, &buf) == -1)
                        {
                                printf("Error opening file \"%s\" for lstat()\n", dent->d_name);
                                exit(EXIT_FAILURE);
                        }

                        if (S_ISDIR(buf.st_mode) && rc)
                        {
                                find(dent->d_name);
                                chdir("..");
                                //when this find() completes, it will be one level down:
                                //so we must come back up again.
                        }
                        if (S_ISREG(buf.st_mode))
                        {
                                fnext = fnextension(dent->d_name);
                                if (*fnext == 'c' || *fnext == 'h')
                                {
                                        consume_comments(dent->d_name);
                                        printf("Comments consumed:%20s\n", dent->d_name);
                                }
                        }
                }
        }
}
+4
source share
3 answers

You can use 1 of 3 solutions

  • As pointed out by @Theolodis comment, ignore files starting at __.
  • 2 . .c .h (). ().
  • .c .h (/tmp linux %TEMP% ) .c .h . .
+4

. , , , ! , !

(: file.c, __file.c __file.c ____file.c, file.c __file.c)

  • , .

    :

    : ,

  • , , . , .

    : ,

    : , .

edit: Mohit Jain !

+1

, chk_prefix() .

char * prefix = "__nmc_";

int chk_prefix (char * name)
{
        int nsize = strlen(name);
        int fsize = strlen(prefix);
        int i;
        if (nsize < fsize) return 1;
        for (i = 0; i < fsize; i++)
        {
                if (name[i] != prefix[i]) return 1;
        }
        return 0;
}

int find (const char * dirname)
{
        int count = 3;
        DIR * dh;
        struct dirent * dent;
        struct stat buf;
        const char * fnext;
        int filecount = 0;

        chdir(dirname);

        if ((dh = opendir(".")) == NULL)
        {
                printf("Error opening directory \"%s\"\n", dirname);
                exit(-1);
        }

        while ((dent = readdir(dh)) != NULL)
        {
                if (count) count--;
                if (!count)
                {
                        if (lstat(dent->d_name, &buf) == -1)
                        {
                                printf("Error opening file \"%s\" for lstat()\n", dent->d_name);
                                exit(EXIT_FAILURE);
                        }

                        if (S_ISDIR(buf.st_mode) && rc)
                        {
                                find(dent->d_name);
                                chdir("..");
                                //when this find() completes, it will be one level down:
                                //so we must come back up again.
                        }
                        if (S_ISREG(buf.st_mode))
                        {
                                fnext = fnextension(dent->d_name);
                                if (*fnext == 'c' || *fnext == 'h' && chk_prefix(dent->d_name))
                                {
                                        consume_comments(dent->d_name);
                                        printf("Comments consumed:%20s\n", dent->d_name);
                                }
                        }
                }
        }
}
+1

Source: https://habr.com/ru/post/1541117/


All Articles